Cyclic Tour
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/65535 K (Java/Others)Total Submission(s): 2327 Accepted Submission(s): 1190
The first line of each test case contains two integers N (N ≤ 100) and M, indicating the number of cities and the number of roads. The M lines followed, each of them contains three numbers A, B, and C, indicating that there is a road from city A to city B, whose length is C. (1 ≤ A,B ≤ N, A ≠ B, 1 ≤ C ≤ 1000).
6 9 1 2 5 2 3 5 3 1 10 3 4 12 4 1 8 4 6 11 5 4 7 5 6 9 6 5 4 6 5 1 2 1 2 3 1 3 4 1 4 5 1 5 6 1
42 -1HintIn the first sample, there are two cycles, (1->2->3->1) and (6->5->4->6) whose length is 20 + 22 = 42.
一个人要旅行,旅行的过程一定是从某个点出发,走一圈之后回到起点,算是一次旅行,问是否在给你n个点,m条有向边的情况下,走完所有城市,如果能,输出最小权值花费,如果不能,输出-1。
思路:
1、最开始看到需要走一个圈的时候可能稍微有点绕,不知道从何下手比较好,其实并不难,首先我们对应想到如果从一个点出发,再回到这个点,如果对应有流需要流过的话,其实对应我们可以将点i拆成两个点i,i+n,一个用来表示起点,一个用来表示终点。
2、那么问题转化到费用流上来:
①建立源点S,将源点连入各个节点(1-n),费用为0,容量为1.表示一个点只能走一次。
②建立汇点T,将各个拆点连入汇点(n+1-2n),费用为0,容量为1。
③对应m条有向边,将u连入v+n,费用为其权值,容量为INF。
那么对应一个简单的三个点组成的环的建图情况:
很明显,跑完费用流的maxflow=3;
那么如果少了3->1这条有向边,很明显maxlfow=2;
3、那么我们得到结论:建好图之后跑费用流,如果最大流==n,输出最小花费,否则输出-1、
Ac代码:
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
using namespace std;
struct node
{
int from;
int to;
int w;
int f;
int num;
int next;
}e[151515];
int n,m,cont,ss,tt;
int path[15000];
int pre[15000];
int dis[15000];
int vis[15000];
int head[15000];
void add(int from,int to,int w,int f)
{
e[cont].num=cont;
e[cont].to=to;
e[cont].w=w;
e[cont].f=f;
e[cont].next=head[from];
head[from]=cont++;
}
void getmap()
{
ss=n*2+1;
tt=ss+1;
cont=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
{
add(ss,i,0,1);
add(i,ss,0,0);
add(i+n,tt,0,1);
add(tt,i+n,0,0);
}
for(int i=0;i<m;i++)
{
int x,y,w;
scanf("%d%d%d",&x,&y,&w);
add(x,y+n,w,0x3f3f3f3f);
add(y+n,x,-w,0);
}
}
int SPFA()
{
for(int i=1;i<=tt;i++)dis[i]=0x3f3f3f3f;
dis[ss]=0;
memset(vis,0,sizeof(vis));
queue<int >s;
s.push(ss);
while(!s.empty())
{
int u=s.front();
s.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
int w=e[i].w;
int f=e[i].f;
if(f&&dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
pre[v]=u;
path[v]=e[i].num;
if(vis[v]==0)
{
vis[v]=1;
s.push(v);
}
}
}
}
if(dis[tt]==0x3f3f3f3f)return 0;
else return 1;
}
void MCMF()
{
int ans=0;
int maxflow=0;
while(SPFA()==1)
{
int minn=0x3f3f3f3f;
for(int i=tt;i!=ss;i=pre[i])
{
minn=min(e[path[i]].f,minn);
}
for(int i=tt;i!=ss;i=pre[i])
{
e[path[i]].f-=minn;
e[path[i]^1].f+=minn;
}
ans+=minn*dis[tt];
maxflow+=minn;
}
if(maxflow!=n)printf("-1\n");
else printf("%d\n",ans);
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
getmap();
MCMF();
}
}
/*
4 4
1 2 3
2 3 4
3 1 4
3 4 2
*/