#HDU3435#A new Graph Game(环+KM)

来源:互联网 发布:java zxing 二维码 编辑:程序博客网 时间:2024/05/16 17:16

A new Graph Game

Time Limit: 8000/4000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 2721    Accepted Submission(s): 1068


Problem Description
An undirected graph is a graph in which the nodes are connected by undirected arcs. An undirected arc is an edge that has no arrow. Both ends of an undirected arc are equivalent--there is no head or tail. Therefore, we represent an edge in an undirected graph as a set rather than an ordered pair.
Now given an undirected graph, you could delete any number of edges as you wish. Then you will get one or more connected sub graph from the original one (Any of them should have more than one vertex).
You goal is to make all the connected sub graphs exist the Hamiltonian circuit after the delete operation. What’s more, you want to know the minimum sum of all the weight of the edges on the “Hamiltonian circuit” of all the connected sub graphs (Only one “Hamiltonian circuit” will be calculated in one connected sub graph! That is to say if there exist more than one “Hamiltonian circuit” in one connected sub graph, you could only choose the one in which the sum of weight of these edges is minimum).
  For example, we may get two possible sums:

(1)  7 + 10 + 5 = 22
(2)  7 + 10 + 2 = 19
(There are two “Hamiltonian circuit” in this graph!)
 

Input
In the first line there is an integer T, indicates the number of test cases. (T <= 20)
In each case, the first line contains two integers n and m, indicates the number of vertices and the number of edges. (1 <= n <=1000, 0 <= m <= 10000)
Then m lines, each line contains three integers a,b,c ,indicates that there is one edge between a and b, and the weight of it is c . (1 <= a,b <= n, a is not equal to b in any way, 1 <= c <= 10000)
 

Output
Output “Case %d: “first where d is the case number counted from one. Then output “NO” if there is no way to get some connected sub graphs that any of them exists the Hamiltonian circuit after the delete operation. Otherwise, output the minimum sum of weight you may get if you delete the edges in the optimal strategy.


Sample Input
33 41 2 52 1 22 3 103 1 7 3 21 2 31 2 42 21 2 31 2 4
 

Sample Output
Case 1: 19Case 2: NOCase 3: 6
Hint
In Case 1:You could delete edge between 1 and 2 whose weight is 5. In Case 2:It’s impossible to get some connected sub graphs that any of them exists the Hamiltonian circuit after the delete operation.

题目大意:

给出N个点M条边(有重边),删去其中的一些边,使得剩下的图中的每一个点都在一个环上(单点不是环),求剩下边的最小边权和。

若本来就不是环则输出NO。


因为是环,所以每个点有入度出度均为1,取反后直接完备匹配即可。

思路同HDU1853:http://blog.csdn.net/its_elaine/article/details/71075046


在此给出两种解法,关于这两种实现方法的差异见HDU2255:http://blog.csdn.net/its_elaine/article/details/71056992

BFS版:

StatusAcceptedTime483msMemory5520kBLength1769LangG++Submitted2017-05-01 12:35:40Shared

#include<iostream>#include<cstdio>#include<cstdlib>#include<cstring>using namespace std;const int Max=1005;const int inf=0x3f3f3f3f;int T,N,M;int wx[Max],wy[Max],match[Max],pre[Max],slack[Max];int map[Max][Max];bool viy[Max];void getint(int &num){     char c;int fla=1;num=0;     while((c=getchar())<'0'||c>'9')if(c=='-')fla=-1;     while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}     num*=fla; }void Bfs(int k){int px,py=0,delta,yy=0;match[py]=k;memset(slack,0x3f,sizeof(slack));memset(pre,0,sizeof(pre));do{delta=inf;px=match[py];viy[py]=1;for(int i=1; i<=N; ++i)if(!viy[i]){if(wx[px]+wy[i]-map[px][i]<slack[i]){slack[i]=wx[px]+wy[i]-map[px][i];pre[i]=py;}if(slack[i]<delta){delta=slack[i];yy=i;}}for(int i=0; i<=N; ++i)if(viy[i]){wx[match[i]]-=delta;wy[i]+=delta;}else slack[i]-=delta;py=yy;}while(match[py]!=0);while(py){match[py]=match[pre[py]];py=pre[py];}}void Km(){memset(wy,0,sizeof(wy));memset(match,0,sizeof(match));for(int i=1; i<=N; ++i){wx[i]=-inf;for(int j=1; j<=N; ++j)wx[i]=max(wx[i],map[i][j]);}for(int i=1; i<=N; ++i){for(int j=1; j<=N; ++j)viy[j]=0;Bfs(i);}}int main(){getint(T);int tot=0,A,B,C;while(T--){getint(N),getint(M);for(int i=1; i<=N; ++i)for(int j=1; j<=N; ++j)map[i][j]=-inf;for(int i=1; i<=M; ++i){getint(A),getint(B),getint(C);map[A][B]=map[B][A]=max(map[A][B],-C);}Km();int Ans=0;bool flg=1;for(int i=1; i<=N; ++i)if(!match[i] || map[match[i]][i] == -inf){flg=0;break;}else Ans+=map[match[i]][i];if(flg)    printf("Case %d: %d\n",++tot,-Ans);        else printf("Case %d: NO\n",++tot);}return 0;}

DFS版:

StatusAcceptedTime3744msMemory5520kBLength2079LangG++Submitted2017-04-30 19:37:34Shared

#include<iostream>#include<cstdio>#include<cstring>#include<cstdlib>using namespace std;const int Max=1005;const int inf=0x3f3f3f3f;int N,T,M,minz;int map[Max][Max];int wx[Max],wy[Max],match[Max];bool vix[Max],viy[Max];void getint(int &num){     char c;int fla=1;num=0;     while((c=getchar())<'0'||c>'9')if(c=='-')fla=-1;     while(c>='0'&&c<='9'){num=num*10+c-48;c=getchar();}     num*=fla; }bool Hungary(int x){    vix[x]=1;    for(int j=1; j<=N; ++j)if(!viy[j]){        int t=wx[x]+wy[j]-map[x][j];        if(!t){            viy[j]=1;            if(!match[j] || Hungary(match[j])){                match[j]=x;                return 1;            }        }    }    return 0;}void Km(){    memset(wy,0,sizeof(wy));    memset(match,0,sizeof(match));    for(int i=1; i<=N; ++i){        wx[i]=-inf;        for(int j=1; j<=N; ++j)            wx[i]=max(wx[i],map[i][j]);    }    for(int i=1; i<=N; ++i)        while(1){            minz=inf;            for(int j=1; j<=N; ++j)vix[j]=viy[j]=0;            if(Hungary(i))    break;            for(int x=1; x<=N; ++x)if(vix[x])                for(int j=1; j<=N; ++j)if(!viy[j])                    minz=min(minz,wx[x]+wy[j]-map[x][j]);            for(int j=1; j<=N; ++j){                if(vix[j])    wx[j]-=minz;                if(viy[j])    wy[j]+=minz;            }        }}int main(){    getint(T);    int A,B,C,tot=0;    while(T--){        getint(N),getint(M);        for(int i=1; i<=N; ++i)            for(int j=1; j<=N; ++j)                map[i][j]=-inf;        for(int i=1; i<=M; ++i){            getint(A),getint(B),getint(C);            map[B][A]=map[A][B]=max(map[A][B],-C);        }        Km();        int Ans=0;        bool flg=1;        for(int i=1; i<=N; ++i){            if(!match[i] || map[match[i]][i]==-inf){                flg=0;                break;            }            else Ans+=wx[match[i]]+wy[i];        }        if(flg)    printf("Case %d: %d\n",++tot,-Ans);        else printf("Case %d: NO\n",++tot);    }    return 0;}




0 0
原创粉丝点击