`

HDU 3435 A new Graph Game (KM 或 最大流)

    博客分类:
  • ACM
阅读更多

A new Graph Game

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


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
3 3 4 1 2 5 2 1 2 2 3 10 3 1 7 3 2 1 2 3 1 2 4 2 2 1 2 3 1 2 4
 

 

Sample Output
Case 1: 19 Case 2: NO Case 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.
 

 

Author
AekdyCoin
 

 

Source
 

 

Recommend
zhouzeyong
 

 

 

我用的是KM算法,,依旧可用最大流,,//给顶点x和y间添加一条费用d,流量f的边 具体参见:http://blog.csdn.net/hqd_acm/article/details/6581979

 

#include<iostream>
#include<cstdio>
#include<cstring>

using namespace std;

const int N=1010;
const int INF=0x3f3f3f3f;

int n,m,nx,ny;
int linker[N],lx[N],ly[N],slack[N];  //lx,ly为顶标,nx,ny分别为x点集y点集的个数
int visx[N],visy[N],w[N][N];

int DFS(int x){
    visx[x]=1;
    for(int y=1;y<=ny;y++){
        if(visy[y])
            continue;
        int tmp=lx[x]+ly[y]-w[x][y];
        if(tmp==0){
            visy[y]=1;
            if(linker[y]==-1 || DFS(linker[y])){
                linker[y]=x;
                return 1;
            }
        }else if(slack[y]>tmp){ //不在相等子图中slack 取最小的
            slack[y]=tmp;
        }
    }
    return 0;
}

int KM(){
    int i,j;
    memset(linker,-1,sizeof(linker));
    memset(ly,0,sizeof(ly));
    for(i=1;i<=nx;i++)      //lx初始化为与它关联边中最大的
        for(j=1,lx[i]=-INF;j<=ny;j++)
            if(w[i][j]>lx[i])
                lx[i]=w[i][j];
    for(int x=1;x<=nx;x++){
        for(i=1;i<=ny;i++)
            slack[i]=INF;
        while(1){
            memset(visx,0,sizeof(visx));
            memset(visy,0,sizeof(visy));
            if(DFS(x))  //若成功(找到了增广轨),则该点增广完成,进入下一个点的增广
                break;  //若失败(没有找到增广轨),则需要改变一些点的标号,使得图中可行边的数量增加。
                        //方法为:将所有在增广轨中(就是在增广过程中遍历到)的X方点的标号全部减去一个常数d,
                        //所有在增广轨中的Y方点的标号全部加上一个常数d
            int d=INF;
            for(i=1;i<=ny;i++)
                if(!visy[i] && d>slack[i])
                    d=slack[i];
            for(i=1;i<=nx;i++)
                if(visx[i])
                    lx[i]-=d;
            for(i=1;i<=ny;i++)  //修改顶标后,要把所有不在交错树中的Y顶点的slack值都减去d
                if(visy[i])
                    ly[i]+=d;
                else
                    slack[i]-=d;
        }
    }
    int res=0;
    for(i=1;i<=ny;i++){
        if(linker[i]==-1 || w[linker[i]][i]==-INF)
            return -1;
        res+=w[linker[i]][i];
    }
    return -res;
}

int main(){

    //freopen("input.txt","r",stdin);

    int t,cases=0;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&m);
        nx=ny=n;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                w[i][j]=-INF;
        int u,v,cap;
        while(m--){
            scanf("%d%d%d",&u,&v,&cap);
            if(w[u][v]<-cap)
                w[u][v]=w[v][u]=-cap;
        }
        printf("Case %d: ",++cases);
        int ans=KM();
        if(ans!=-1)
            printf("%d\n",ans);
        else
            printf("NO\n");
    }
    return 0;
}

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics