zoukankan      html  css  js  c++  java
  • 【BZOJ1877】[SDOI2009]晨跑 最小费用最大流

    【BZOJ1877】[SDOI2009]晨跑

    Description

    Elaxia最近迷恋上了空手道,他为自己设定了一套健身计划,比如俯卧撑、仰卧起坐等 等,不过到目前为止,他坚持下来的只有晨跑。 现在给出一张学校附近的地图,这张地图中包含N个十字路口和M条街道,Elaxia只能从 一个十字路口跑向另外一个十字路口,街道之间只在十字路口处相交。Elaxia每天从寝室出发 跑到学校,保证寝室编号为1,学校编号为N。 Elaxia的晨跑计划是按周期(包含若干天)进行的,由于他不喜欢走重复的路线,所以 在一个周期内,每天的晨跑路线都不会相交(在十字路口处),寝室和学校不算十字路 口。Elaxia耐力不太好,他希望在一个周期内跑的路程尽量短,但是又希望训练周期包含的天 数尽量长。 除了练空手道,Elaxia其他时间都花在了学习和找MM上面,所有他想请你帮忙为他设计 一套满足他要求的晨跑计划。

    Input

    第一行:两个数N,M。表示十字路口数和街道数。 接下来M行,每行3个数a,b,c,表示路口a和路口b之间有条长度为c的街道(单向)。

    Output

    两个数,第一个数为最长周期的天数,第二个数为满足最长天数的条件下最短的路程长 度。

    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

    HINT

    对于30%的数据,N ≤ 20,M ≤ 120。
    对于100%的数据,N ≤ 200,M ≤ 20000。

    题解:又复习了一下网络流

    题目要求边不能重复走,点也不能重复走,那就拆点,让所有的边流量都为1,然后跑费用流就行了

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    using namespace std;
    int to[50000],next[50000],head[410],cost[50000],flow[50000],d[410],re[410],rv[410],inq[410];
    int n,m,cnt,ans,sum;
    queue<int> q;
    int bfs()
    {
    	int i,u;
    	memset(d,0x3f,sizeof(d));
    	q.push(1),d[1]=0;
    	while(!q.empty())
    	{
    		u=q.front(),q.pop();
    		inq[u]=0;
    		for(i=head[u];i!=-1;i=next[i])
    		{
    			if(flow[i]&&d[to[i]]>d[u]+cost[i])
    			{
    				d[to[i]]=d[u]+cost[i];
    				re[to[i]]=i;
    				rv[to[i]]=u;
    				if(!inq[to[i]])
    				{
    					inq[to[i]]=1;
    					q.push(to[i]);
    				}
    			}
    		}
    	}
    	return d[n]<1000000000;
    }
    void add(int a,int b,int c,int d)
    {
    	to[cnt]=b;
    	flow[cnt]=c;
    	cost[cnt]=d;
    	next[cnt]=head[a];
    	head[a]=cnt++;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	int i,a,b,c,mf;
    	memset(head,-1,sizeof(head));
    	for(i=1;i<=n;i++)	add(i,i+n,1,0),add(i+n,i,0,0);
    	for(i=1;i<=m;i++)
    	{
    		scanf("%d%d%d",&a,&b,&c);
    		if(a!=1)	a=a+n;
    		add(a,b,1,c),add(b,a,0,-c);
    	}
    	while(bfs())
    	{
    		ans++,sum+=d[n];
    		for(i=n;i!=1;i=rv[i])	flow[re[i]]--,flow[re[i]^1]++;
    	}
    	printf("%d %d",ans,sum);
    	return 0;
    }
  • 相关阅读:
    MMORPG大型游戏设计与开发(客户端架构 part14 of vegine)
    java线程与并发(一)
    HTTP学习笔记(五)
    http学习笔记(四)——HTTP报文
    http学习笔记(三)
    http学习笔记(二)—— 嘿!伙计,你在哪?(URL)
    http学习笔记(一)
    本地DNS安装
    SQL Server求解连续操作(登录)数量(次数)最大的记录(用户)问题
    一个有趣的SQL Server 层级汇总数据问题
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/6490282.html
Copyright © 2011-2022 走看看