1. 程式人生 > >5991 Cliques 2016ACM/ICPC亞洲區青島站 J (dfs)

5991 Cliques 2016ACM/ICPC亞洲區青島站 J (dfs)

題意:給出一個矩陣表示的無向圖,可以增邊和刪邊使得任意子圖中,任意點之間都連有一條邊,最多增刪10次,輸出最小次數

分析:運用了floyd和點覆蓋集的思想,對於一條已經連好的邊,找到一個點和這條邊的一個點有連邊而和另一個點沒有連邊,修改這三個點的連邊情況,dfs即可

程式碼:

#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define FRER() freopen("i.txt","r",stdin);
#define FREW() freopen("o.txt","w",stdout);
using namespace std;
typedef long long ll;
const int maxn = 100 + 7;
int G[maxn][maxn];
int n,res;
void scan_d(int &ret){
    char c;
    ret = 0;
    while((c=getchar())<'0'||c>'9');
    while(c>='0'&&c<='9'){
        ret = ret*10 + (c-'0'), c= getchar();
    }
}
void dfs(int d){
   // cout<<d<<endl;
    if(d>=res)return;
    int a,b,c;
    a = b = c = 0;
    for(int i=1;i<=n&&!a;i++){
        for(int j=i+1;j<=n&&!a;j++){
            if(G[i][j]){
                for(int k=1;k<=n&&!a;k++){
                    if(i!=k&&j!=k&&(G[i][k]^G[k][j])){
                        a = i;
                        b = j;
                        c = k;
                    }
                }
            }
        }
    }
    if(!a){
        res = d;
        return;
    }
    G[a][b] = G[b][a] = G[a][b]^1;
    dfs(d+1);
    G[a][b] = G[b][a] = G[a][b]^1;

    G[a][c] = G[c][a] = G[a][c]^1;
    dfs(d+1);
    G[a][c] = G[c][a] = G[a][c]^1;

    G[b][c] = G[c][b] = G[b][c]^1;
    dfs(d+1);
    G[b][c] = G[c][b] = G[b][c]^1;
}
int main(){
    //freopen("i.txt","r",stdin);
    int T,k=1;
    scan_d(T);
    while(T--){
        scan_d(n);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                scan_d(G[i][j]);
        res = 11;
        dfs(0);
        printf("Case #%d: %d\n",k++,res==11?-1:res);
    }
    return 0;
}