HDU3488:Tour

来源:互联网 发布:unity3d 2d游戏教程 编辑:程序博客网 时间:2024/05/21 07:47

点击打开题目链接

Tour

Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others)
Total Submission(s): 1387    Accepted Submission(s): 729


Problem Description
In the kingdom of Henryy, there are N (2 <= N <= 200) cities, with M (M <= 30000) one-way roads connecting them. You are lucky enough to have a chance to have a tour in the kingdom. The route should be designed as: The route should contain one or more loops. (A loop is a route like: A->B->……->P->A.)
Every city should be just in one route.
A loop should have at least two cities. In one route, each city should be visited just once. (The only exception is that the first and the last city should be the same and this city is visited twice.)
The total distance the N roads you have chosen should be minimized.
 

Input
An integer T in the first line indicates the number of the test cases.
In each test case, the first line contains two integers N and M, indicating the number of the cities and the one-way roads. Then M lines followed, each line has three integers U, V and W (0 < W <= 10000), indicating that there is a road from U to V, with the distance of W.
It is guaranteed that at least one valid arrangement of the tour is existed.
A blank line is followed after each test case.
 

Output
For each test case, output a line with exactly one integer, which is the minimum total distance.
 

Sample Input
16 91 2 52 3 53 1 103 4 124 1 84 6 115 4 75 6 96 5 4
 

Sample Output
42
 

Source
2010 ACM-ICPC Multi-University Training Contest(6)——Host by BIT
 

Recommend
zhouzeyong
 


=====================================题目大意=====================================


设计路线来游历有着N个城市,M条单向道路的Henryy王国,路线需满足以下几点:

1、每条路线都必须包含至少一个环。

2、每个城市都只能在一条路线上。

3、一个环至少包含两个城市,一条路线上每个城市都只能经过一次。

4、所有路线所包含的N条道路的长度和必须最小。


=====================================算法分析=====================================


根据题意前三点可知,在旅游路线中,每个城市都会作为道路的起点和终点各一次且恰好各一次。

那么只需要令X集合 = 城市集合(代表起点),Y集合 = 城市集合(代表终点),城市A至城市B的单向路 = X中A至Y中B的边

(读入时注意处理重边)

则任意一种满足前三点题意的旅游路线都是X与Y的一个最大匹配。

考虑到题意第四点,那么本题即求二分图最佳完美匹配,只不过这里的完美指的是权和最小而已。


=======================================代码=======================================



#include<stdio.h>#include<string.h>#define MIN(A,B)  ((A)<(B)?(A):(B))#define MAX(A,B)  ((A)>(B)?(A):(B))const int INF1=0x7f;const int INF4=0x7f7f7f7f;const int MAXN=305;int T,N,M,Edge[MAXN][MAXN],Linker[MAXN];int TopX[MAXN],TopY[MAXN],Slack[MAXN];bool VisX[MAXN],VisY[MAXN];bool DFS(int X){VisX[X]=true;for(int y=1;y<=N;++y) if(!VisY[y]){//最大权:(TopX[X]+TopY[y])-Edge[X][y] //最小权:Edge[X][y]-(TopX[X]+TopY[y])int slacklen=Edge[X][y]-(TopX[X]+TopY[y]);     if(slacklen){Slack[y]=MIN(Slack[y],slacklen);}else{VisY[y]=true;if(Linker[y]==-1||DFS(Linker[y])){Linker[y]=X;  return true;}}}return false;}void UpdateTop(){int addconst=INF4;for(int y=1;y<=N;++y){ if(!VisY[y]) { addconst=MIN(addconst,Slack[y]); }}for(int i=1;i<=N;++i){//最大权:-=//最小权:+=if(VisX[i])  { TopX[i]+=addconst; }    //最大权:+=//最小权:-=if(VisY[i])  { TopY[i]-=addconst; }    if(!VisY[i]) { Slack[i]-=addconst; } }}int KM(){memset(TopX,INF1,sizeof(TopX));memset(TopY,0,sizeof(TopY));memset(Linker,-1,sizeof(Linker));for(int x=1;x<=N;++x){for(int y=1;y<=N;++y){    //最大权:MAX     //最小权:MINTopX[x]=MIN(TopX[x],Edge[x][y]);   }}for( x=1;x<=N;++x) while(1){memset(VisX,0,sizeof(VisX));memset(VisY,0,sizeof(VisY));memset(Slack,INF1,sizeof(Slack));if(DFS(x)) { break; }else { UpdateTop(); }}int sum=0;for(int i=1;i<=N;++i){sum+=TopX[i];sum+=TopY[i];}return sum;}int main(){while(scanf("%d",&T)==1) while(T--){scanf("%d%d",&N,&M);//最大权:INF1=0xef//最小权:INF1=0x7f memset(Edge,INF1,sizeof(Edge));          for(int i=1;i<=M;++i){int u,v,w;scanf("%d%d%d",&u,&v,&w);if(w<Edge[u][v]) { Edge[u][v]=w; }}printf("%d\n",KM());}return 0;}
原创粉丝点击