hdu 1853 Cyclic Tour(费用流,判断满流)
2016-07-30 09:58
441 查看
Cyclic Tour
Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/65535 K (Java/Others)Total Submission(s): 2232 Accepted Submission(s): 1138
Problem Description
There are N cities in our country, and M one-way roads connecting them. Now Little Tom wants to make several cyclic tours, which satisfy that, each cycle contain at least two cities, and each city belongs to one cycle exactly. Tom wants the total length of
all the tours minimum, but he is too lazy to calculate. Can you help him?
Input
There are several test cases in the input. You should process to the end of file (EOF).
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).
Output
Output one number for each test case, indicating the minimum length of all the tours. If there are no such tours, output -1.
Sample Input
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
Sample Output
42
-1
Hint In the first sample, there are two cycles, (1->2->3->1) and (6->5->4->6) whose length is 20 + 22 = 42.
题意:有n个城市,现在让n个城市形成1个或者多个圈,问最少的距离
如果不行输出-1
思路:形成一个或多个圈,明显的可以构造二分图出来。
然后用KM算法或者费用流即可。 注意不行的情况是非满流,判断下即可。
hdu3488是这个题目的升级版,数据量翻倍了,TLE= =
估计还是得用KM算法
代码:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
using namespace std;
#define N 1010
#define M 30010
#define INF 0x3f3f3f3f
struct Node
{
int from,to,next,cap,cost;///起点,终点,同起点下一条边,残余流量,费用
} edge[M*7];
int cnt,head
;
int vis
,d
,pp
;
int sumflow;///最大流量总和
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
void addedge(int from,int to,int cap,int cost)
{
edge[cnt].from=from;
edge[cnt].to=to;
edge[cnt].cost=cost;
edge[cnt].cap=cap;
edge[cnt].next=head[from];
head[from]=cnt++;
edge[cnt].from=to;
edge[cnt].to=from;
edge[cnt].cost=-cost;
edge[cnt].cap=0;
edge[cnt].next=head[to];
head[to]=cnt++;///存反向边
}
int spfa(int s,int t,int n)
{
queue<int>q;
memset(vis,0,sizeof(vis));
memset(pp,-1,sizeof(pp));///pp[i]表示最短路径上以i为终点的边的编号
for(int i=0; i<=n; i++)
d[i]=INF;
d[s]=0;
vis[s]=1;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap>0&&d[v]>d[u]+edge[i].cost)
{
d[v]=d[u]+edge[i].cost;
pp[v]=i;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
if(d[t]==INF) return 0;///找不到一条到终点的路
return 1;
}
int MCMF(int s,int t,int n)
{
int mincost=0,minflow,flow=0;///最小费用,路径中最小流量,总流量
while(spfa(s,t,n))///找当前的最短路
{
minflow=INF+1;
for(int i=pp[t]; i!=-1; i=pp[edge[i].from])
minflow=min(minflow,edge[i].cap);///从路径中找最小的流量
flow+=minflow;///总流量加上最小流量
for(int i=pp[t]; i!=-1; i=pp[edge[i].from])
{
edge[i].cap-=minflow;///当前边减去最小流量
edge[i^1].cap+=minflow;///反向边加上最小流量
}
mincost+=d[t]*minflow;///最小费用等于路径和*每条路径的流量(经过多少次)
}
sumflow=flow;
return mincost;
}
int main()
{
int n,m,T;
int from,to,cost;
while(~scanf("%d %d",&n,&m))
{
init();
for(int i=0; i<m; i++)
{
scanf("%d %d %d",&from,&to,&cost);
addedge(from,to+n,1,cost);
}
int S=0,T=2*n+1;
for(int i=1; i<=n; i++)
addedge(S,i,1,0);
for(int i=n+1;i<=2*n;i++)
addedge(i,T,1,0);
int ans=MCMF(S,T,T);///流量为2保证只会走两次,如果是1到n有可能走多次
if(sumflow==n) printf("%d\n",ans);
else printf("-1\n");
}
return 0;
}
相关文章推荐
- GZIP压缩原理分析(01)——第一章 序言
- Print all Jumping Numbers smaller than or equal to a given value
- 精选30道Java笔试题(原网站:http://www.cnblogs.com/lanxuezaipiao/p/3371224.html)
- GIS基础软件及操作(九)
- GIS基础软件及操作(八)
- 剑指offer——链表中倒数第k个结点
- ==equals的区别
- 常用数据库高可用和分区解决方案(1) — MySQL篇
- Uva156 map容器的使用 sortvecor And map.count
- 浏览器指纹的消除
- android--进度框(ProgressBar)
- [2016-7-29]每日总结
- 编写OC代码时的注意事项
- CodeForces 702 A Maximum Increase (贪心,高效算法)
- GIS基础软件及操作(七)
- Visual Studio Code 怎么支持中文
- UVA 536 - Tree Recovery
- linux 查看CPU个数
- 常用数据库高可用和分区解决方案(2) — Oracle篇
- Linux下的ELF可执行文件学习总结