当前位置: 首页 > 工具软件 > Tutti > 使用案例 >

zzuoj--10459--Tutti!(最小费用拆点)

苏鸿志
2023-12-01



10459: Tutti!

Time Limit: 10 Sec   Memory Limit: 128 MB
Submit: 19   Solved: 5
[ Submit][ Status][ Web Board]

Description

因为Raywzy计划在清明节去爬泰山,所以他决定在去之前好好的锻炼一下身体,跑步是很好的办法!在zzu内,假设有N个房子,M条十字路口,保证寝室编号为1,实验室编号为N。Raywzy只能从一个十字路口跑向另一个十字路口,街道
之间只在十字路口处相交。
Raywzy的跑步计划是按周期进行的,而且他不喜欢走重复的路线,即每天选择一条不同的路线。除了1和N之外,每个点只能走一次。但是Raywzy十分的瘦弱,所以他想尽可能跑短的路线。现在Raywzy希望你可以为他定一个训练计划。
Raywzy每天的起点是1,目的地是实验室~~
内容与题目无关=w=

Input

数据保证单组
第一行2个数n,m。表示十字路口数和街道数。
接下来m行,每行3个数a,b,c,表示十字路口a和十字路口b之间有条长度为c的单向街道。

Output

2个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长度(即长度和)。

Sample Input

7 10
1 2 1
1 3 1
2 4 1
3 4 1
4 5 1
4 6 1
2 5 5
3 6 6
5 7 1
6 7 1

Sample Output

2 11
#include<cstdio>
#include<cstring>
#include<queue>
#include<stack>
#include<algorithm>
using namespace std;
#define MAXN 10100
#define INF 0x3f3f3f3f
struct node
{
	int u,v,cap,flow,cost,next;
}edge[MAXN*50];
int n,m,vis[MAXN],dis[MAXN],pre[MAXN],head[MAXN],cnt1;
void init()
{
	memset(head,-1,sizeof(head));
	cnt1=0;
}
void add(int a,int b,int c,int d)
{
	node E={a,b,c,0,d,head[a]};
	edge[cnt1]=E;
	head[a]=cnt1++;
	node E1={b,a,0,0,-d,head[b]};
	edge[cnt1]=E1;
	head[b]=cnt1++;
}
bool BFS(int s,int t)
{
	memset(vis,0,sizeof(vis));
	memset(dis,INF,sizeof(dis));
	memset(pre,-1,sizeof(pre));
	vis[s]=1;
	dis[s]=0;
	queue<int>q;
	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)
		{
			node E=edge[i];
			if(dis[E.v]>dis[u]+E.cost&&E.cap>E.flow)
			{
				dis[E.v]=dis[u]+E.cost;
				pre[E.v]=i;
				if(!vis[E.v])
				{
					q.push(E.v);
					vis[E.v]=1;
				}
			}
		}
	}
	return pre[t]!=-1;
}
void mcmf(int s,int t,int &flow,int &cost)
{
	flow=cost=0;
	while(BFS(s,t))
	{
		int Min=INF;
		for(int i=pre[t];i!=-1;i=pre[edge[i^1].v])
		{
			node E=edge[i];
			Min=min(Min,E.cap-E.flow);
		}
		for(int i=pre[t];i!=-1;i=pre[edge[i^1].v])
		{
			edge[i].flow+=Min;
			edge[i^1].flow-=Min;
			cost+=edge[i].cost*Min;
		}
		flow+=Min;
	}
}
int main()
{
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		int u,v,w;
		init();
		for(int i=2;i<=n-1;i++)
		add(i,i+n,1,0);//保证除了1,n其他的只可以用一次 
		for(int i=0;i<m;i++)
		{
			scanf("%d%d%d",&u,&v,&w);
			if(u!=1&&u!=n) u+=n;
			add(u,v,1,w);
		}
		int cost,flow;
		mcmf(1,n,flow,cost);
		printf("%d %d\n",flow,cost);
	}
	return 0;
}

 类似资料: