HDU 3435 A new Graph Game(费用流)

题意:给你一个N个节点M条边的无向图,要你求该图有1个或多个不相交有向环构成时,所有这些有向环的最小权值.

思路:和HDU1853差不多,只是变成了无向图,那么把一条无向边变成两条相反方向的有向边即可

注意:有重边,要处理一下


#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
#include<vector>
#define INF 1e9
using namespace std;
const int maxn=2500;
int T,cas=1;
struct Edge
{
    int from,to,cap,flow,cost;
    Edge(){}
    Edge(int f,int t,int c,int fl,int co):from(f),to(t),cap(c),flow(fl),cost(co){}
};

struct MCMF
{
    int n,m,s,t;
    vector<Edge> edges;
    vector<int> G[maxn];
    bool inq[maxn];     //是否在队列
    int d[maxn];        //Bellman_ford单源最短路径
    int p[maxn];        //p[i]表从s到i的最小费用路径上的最后一条弧编号
    int a[maxn];        //a[i]表示从s到i的最小残量

    //初始化
    void init(int n,int s,int t)
    {
        this->n=n, this->s=s, this->t=t;
        edges.clear();
        for(int i=0;i<n;++i) G[i].clear();
    }

    //添加一条有向边
    void AddEdge(int from,int to,int cap,int cost)
    {
        edges.push_back(Edge(from,to,cap,0,cost));
        edges.push_back(Edge(to,from,0,0,-cost));
        m=edges.size();
        G[from].push_back(m-2);
        G[to].push_back(m-1);
    }

    //求一次增广路
    bool BellmanFord(int &flow, int &cost)
    {
        for(int i=0;i<n;++i) d[i]=INF;
        memset(inq,0,sizeof(inq));
        d[s]=0, a[s]=INF, inq[s]=true, p[s]=0;
        queue<int> Q;
        Q.push(s);
        while(!Q.empty())
        {
            int u=Q.front(); Q.pop();
            inq[u]=false;
            for(int i=0;i<G[u].size();++i)
            {
                Edge &e=edges[G[u][i]];
                if(e.cap>e.flow && d[e.to]>d[u]+e.cost)
                {
                    d[e.to]= d[u]+e.cost;
                    p[e.to]=G[u][i];
                    a[e.to]= min(a[u],e.cap-e.flow);
                    if(!inq[e.to]){ Q.push(e.to); inq[e.to]=true; }
                }
            }
        }
        if(d[t]==INF) return false;
        flow +=a[t];
        cost +=a[t]*d[t];
        int u=t;
        while(u!=s)
        {
            edges[p[u]].flow += a[t];
            edges[p[u]^1].flow -=a[t];
            u = edges[p[u]].from;
        }
        return true;
    }

    //求出最小费用最大流
    int Min_cost(int num)
    {
        int flow=0,cost=0;
        while(BellmanFord(flow,cost));
        return num==flow?cost:-1;
    }
}mc;

int d[maxn][maxn];

int main()
{
	int n,m;
	scanf("%d",&T);
    while (T--)
	{	
        scanf("%d%d",&n,&m);
        mc.init(n*2+2,0,n*2+1);
		memset(d,0,sizeof(d));
		for (int i=1;i<=n;i++)
		{
			mc.AddEdge(0,i,1,0);
			mc.AddEdge(n+i,n*2+1,1,0);
		}
		for (int i = 1;i<=m;i++)
		{
			int u,v,w;
			scanf("%d%d%d",&u,&v,&w);
			if (d[u][v] > w || !d[u][v])
			{
				d[u][v]=w;
				d[v][u]=w;
			}
		}
		for (int i = 1;i<=n;i++)
			for (int j = i+1;j<=n;j++)
				if (d[i][j]!=0)
				{
					mc.AddEdge(i,j+n,1,d[i][j]);
                    mc.AddEdge(j,i+n,1,d[i][j]);
				}
        
		int ans = mc.Min_cost(n);
		if (ans == -1)
			printf("Case %d: NO\n",cas++);
		else
		    printf("Case %d: %d\n",cas++,ans);
	}
} 


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. 
         
 


你可能感兴趣的:(HDU 3435 A new Graph Game(费用流))