zoukankan      html  css  js  c++  java
  • 【BZOJ2095】[Poi2010]Bridges 动态加边网络流

    【BZOJ2095】[Poi2010]Bridges

    Description

    YYD为了减肥,他来到了瘦海,这是一个巨大的海,海中有n个小岛,小岛之间有m座桥连接,两个小岛之间不会有两座桥,并且从一个小岛可以到另外任意一个小岛。现在YYD想骑单车从小岛1出发,骑过每一座桥,到达每一个小岛,然后回到小岛1。霸中同学为了让YYD减肥成功,召唤了大风,由于是海上,风变得十分大,经过每一座桥都有不可避免的风阻碍YYD,YYD十分ddt,于是用泡芙贿赂了你,希望你能帮他找出一条承受的最大风力最小的路线。

    Input

    输入:第一行为两个用空格隔开的整数n(2<=n<=1000),m(1<=m<=2000),接下来读入m行由空格隔开的4个整数a,b(1<=a,b<=n,a<>b),c,d(1<=c,d<=1000),表示第i+1行第i座桥连接小岛a和b,从a到b承受的风力为c,从b到a承受的风力为d。

    Output

    输出:如果无法完成减肥计划,则输出NIE,否则第一行输出承受风力的最大值(要使它最小)

    Sample Input

    4 4
    1 2 2 4
    2 3 3 4
    3 4 4 4
    4 1 5 4

    Sample Output

    4

    题解:混合图欧拉回路做法:先将所有边随意定向,然后从S向所有度数为正的点连边,度数为负的点向T连边,再连上原图的反向边,跑最大流看是否有解即可。

    对于本题,我们可以先对于每条边选取阻力较小的那个方向,然后将按另一个方向的阻力排序,从小到大扔到图中,如果扔进去之后满流了,则输出答案即可。

    网上部分用二分做的代码有问题,可以被hack。

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <queue>
    #include <algorithm>
    using namespace std;
    int n,m,ans,sum,cnt,S,T;
    struct node
    {
    	int a,b,c,d;
    }p[2010];
    int to[10010],next[10010],val[10010],head[1010],d[1010];
    queue<int> q;
    bool cmp(const node &a,const node &b)
    {
    	return a.d<b.d;
    }
    inline void add(int a,int b,int c)
    {
    	to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
    	to[cnt]=a,val[cnt]=0,next[cnt]=head[b],head[b]=cnt++;
    }
    int dfs(int x,int mf)
    {
    	if(x==T)	return mf;
    	int i,k,temp=mf;
    	for(i=head[x];i!=-1;i=next[i])	if(d[to[i]]==d[x]+1&&val[i])
    	{
    		k=dfs(to[i],min(temp,val[i]));
    		if(!k)	d[to[i]]=0;
    		val[i]-=k,val[i^1]+=k,temp-=k;
    		if(!temp)	break;
    	}
    	return mf-temp;
    }
    int bfs()
    {
    	memset(d,0,sizeof(d));
    	while(!q.empty())	q.pop();
    	int i,u;
    	q.push(S),d[S]=1;
    	while(!q.empty())
    	{
    		u=q.front(),q.pop();
    		for(i=head[u];i!=-1;i=next[i])	if(!d[to[i]]&&val[i])
    		{
    			d[to[i]]=d[u]+1;
    			if(to[i]==T)	return 1;
    			q.push(to[i]);
    		}
    	}
    	return 0;
    }
    inline int rd()
    {
    	int ret=0,f=1;	char gc=getchar();
    	while(gc<'0'||gc>'9')	{if(gc=='-')	f=-f;	gc=getchar();}
    	while(gc>='0'&&gc<='9')	ret=ret*10+(gc^'0'),gc=getchar();
    	return ret*f;
    }
    int main()
    {
    	n=rd(),m=rd();
    	int i;
    	for(i=1;i<=m;i++)
    	{
    		p[i].a=rd(),p[i].b=rd(),p[i].c=rd(),p[i].d=rd();
    		if(p[i].c>p[i].d)	swap(p[i].a,p[i].b),swap(p[i].c,p[i].d);
    		d[p[i].a]++,d[p[i].b]--;
    		ans=max(ans,p[i].c);
    	}
    	sort(p+1,p+m+1,cmp);
    	memset(head,-1,sizeof(head));
    	S=0,T=n+1;
    	for(i=1;i<=n;i++)
    	{
    		if(d[i]&1)
    		{
    			printf("NIE");
    			return 0;
    		}
    		d[i]>>=1;
    		if(d[i]>0)	add(S,i,d[i]),sum+=d[i];
    		if(d[i]<0)	add(i,T,-d[i]);
    	}
    	if(sum)	for(i=1;i<=m;i++)
    	{
    		add(p[i].a,p[i].b,1);
    		ans=max(ans,p[i].d);
    		while(bfs())	sum-=dfs(S,1<<30);
    		if(!sum)	break;
    	}
    	if(sum)	printf("NIE");
    	else	printf("%d",ans);
    	return 0;
    }
     
  • 相关阅读:
    简要概括java技术体系
    我的学习之旅
    Ubuntu18.04系统执行语句时出现错误Failed to load module "canberra-gtk-module"
    USRPX310 在GNU Radio上更改通道A或B
    ubuntu18.04 安装UHD+GNU Radio教程
    安装WIN10+Ubuntu18.04安装教程(实测有效)
    信道编码
    IQ基础
    清除LabVIEW中波形图表或波形图中的历史数据
    LabVIEW中的波形图表(Chart)与波形图(Graph)
  • 原文地址:https://www.cnblogs.com/CQzhangyu/p/7787691.html
Copyright © 2011-2022 走看看