zoukankan      html  css  js  c++  java
  • 【HDU 3435】 A new Graph Game (KM|费用流)

    A new Graph Game



    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.
     
     
    【题意】
      将一个无向图删边得到一些子图,并使每个子图中存在哈密顿回路,并使所有哈密顿回路上边的权值最小
     
    【分析】
      形成哈密顿回路的话就是每个点入度出度都为0.拆点建二分图,然后KM。
     
    这题要判断能不能完美匹配,这里修改一下模版!!
    INF 那里要判断一下再减delta!!
     
    代码如下:
      1 #include<cstdio>
      2 #include<cstdlib>
      3 #include<cstring>
      4 #include<iostream>
      5 #include<algorithm>
      6 #include<queue>
      7 using namespace std;
      8 #define Maxn 1010
      9 #define Maxm 10010
     10 #define INF 0xfffffff
     11 
     12 struct node
     13 {
     14     int x,y,c,next;
     15 }t[Maxm*2];int len;
     16 int first[Maxn];
     17 
     18 void ins(int x,int y,int c)
     19 {
     20     t[++len].x=x;t[len].y=y;t[len].c=-c;
     21     t[len].next=first[x];first[x]=len;
     22 }
     23 
     24 int mymin(int x,int y) {return x<y?x:y;}
     25 int mymax(int x,int y) {return x>y?x:y;}
     26 
     27 int lx[Maxn],ly[Maxn];
     28 int slack[Maxn],match[Maxn];
     29 bool visx[Maxn],visy[Maxn];
     30 int n;
     31 
     32 bool ffind(int x)
     33 {
     34     visx[x]=1;
     35     for(int i=first[x];i;i=t[i].next) if(!visy[t[i].y])
     36     {
     37         int y=t[i].y;
     38         if(t[i].c==lx[x]+ly[y])
     39         {
     40             visy[y]=1;
     41             if(!match[y]||ffind(match[y]))
     42             {
     43                 match[y]=x;
     44                 return 1;
     45             }
     46         }
     47         else slack[y]=mymin(slack[y],lx[x]+ly[y]-t[i].c);
     48     }
     49     return 0;
     50     
     51 }
     52 
     53 bool solve()
     54 {
     55     memset(match,0,sizeof(match));
     56     memset(ly,0,sizeof(ly));
     57     for(int i=1;i<=n;i++)
     58     {
     59         lx[i]=-INF;
     60             // printf("%d
    ",i);
     61         for(int j=first[i];j;j=t[j].next)
     62         {
     63             // printf("%d
    ",j);
     64            lx[i]=mymax(lx[i],t[j].c);
     65             
     66         }
     67     }
     68     int i;
     69     for(i=1;i<=n;i++)
     70     {
     71         for(int j=1;j<=n;j++) slack[j]=INF;
     72         while(1)
     73         {
     74             memset(visx,0,sizeof(visx));
     75             memset(visy,0,sizeof(visy));
     76             if(ffind(i)) break;
     77             int delta=INF;
     78             for(int j=1;j<=n;j++) if(!visy[j])
     79                 delta=mymin(delta,slack[j]);
     80             if(delta==INF) return 0;
     81             for(int j=1;j<=n;j++)
     82             {
     83                 if(visx[j]) lx[j]-=delta;
     84                 if(visy[j]) ly[j]+=delta;
     85                 else if(slack[j]!=INF) slack[j]-=delta;
     86             }
     87         }
     88     }
     89     return 1;
     90 }
     91 
     92 int main()
     93 {
     94     int T,kase=0;
     95     scanf("%d",&T);
     96     while(T--)
     97     {
     98         int m;
     99         scanf("%d%d",&n,&m);
    100         len=0;
    101         memset(first,0,sizeof(first));
    102         for(int i=1;i<=m;i++)
    103         {
    104             int x,y,c;
    105             scanf("%d%d%d",&x,&y,&c);
    106             ins(x,y,c);ins(y,x,c);
    107         }
    108         printf("Case %d: ",++kase);
    109         if(solve())
    110         {
    111             int ans=0;
    112             for(int i=1;i<=n;i++) ans+=lx[i]+ly[i];
    113             printf("%d
    ",-ans);
    114         }
    115         else printf("NO
    ");
    116     }
    117     return 0;
    118 }
    [HDU 3435]

    2016-10-27 11:12:02

  • 相关阅读:
    Transaction 'IREG', Abend 'APCT', at '????'.
    CICS中设置是否具有可修改性
    常用命令总结
    常用语句总结
    _func_
    数组排序返回索引-python和c++的实现
    数组的并行求和-cuda实现
    Pytorch 多GPU训练-多计算节点并行-All you need
    Pytorch 多GPU训练-单运算节点-All you need
    Windows 编程中的问题
  • 原文地址:https://www.cnblogs.com/Konjakmoyu/p/6003202.html
Copyright © 2011-2022 走看看