zoukankan      html  css  js  c++  java
  • POJ1637 Sightseeing Tour

    传送门

    建模非常神奇的脑子题(不适合我

    一句话题意:混合图欧拉回路

    首先我们知道如果一个图存在欧拉图的话那么每个点的入度要等于出度

    那么对于单向边我们可以确定下来入度出度可以直接加到点上然后删掉

    双向边我们需要给它定向来决定是否存在欧拉回路

    我们需要让每个点达到流量平衡也就是入度=出度

    我们先任意定向使每个点现在有一个确定的入度和出度

    然后我们需要重定向是流量平衡

    所以我们将入度>出度的点连源点 入度<出度的连汇点 等于的不需要考虑因为本来已经符合要求了嘛

    流量是delta/2(delta是入度出度差的绝对值) 这个除以2是因为一条边变向的话其实是更改了出度也更改了入度 所以变化值是两倍 流量就要设为原来的1/2

    其他的边按照我们刚才任意定向的连接流量为1的边即可(最后残存流量为1的话就是保持原样 0的话就是反向)

    这样的话我们只需要看是否是满流就可以了

    注意初始化。。。

    附代码。

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #define inf 20021225
    #define ll long long
    using namespace std;
    
    struct edge{int to,lt,f;}e[3010];
    queue<int> que;int in[410],cnt=-1,s,t,dep[410];
    int ii[410],oo[410],xx[1010],yy[1010],d[1010];
    void add(int x,int y,int f)
    {
    	e[++cnt].f=f;e[cnt].to=y;e[cnt].lt=in[x];in[x]=cnt;
    	e[++cnt].f=0;e[cnt].to=x;e[cnt].lt=in[y];in[y]=cnt;
    }
    bool bfs()
    {
    	while(!que.empty())	que.pop();
    	memset(dep,0,sizeof(dep));
    	dep[s]=1;que.push(s);
    	while(!que.empty())
    	{
    		int x=que.front();que.pop();
    		for(int i=in[x];i;i=e[i].lt)
    		{
    			int y=e[i].to;
    			if(!dep[y]&&e[i].f)
    			{
    				dep[y]=dep[x]+1;
    				if(y==t)	return 1;
    				que.push(y);
    			}
    	//printf("QAQ");
    		}
    	}
    	return 0;
    }
    int dfs(int x,int flow)
    {
    	if(x==t||!flow)	return flow;
    	int cur=0;
    	for(int i=in[x];i;i=e[i].lt)
    	{
    		int y=e[i].to;
    		if(dep[y]==dep[x]+1&&e[i].f)
    		{
    			int tmp=dfs(y,min(e[i].f,flow-cur));
    			cur+=tmp;e[i].f-=tmp;e[i^1].f+=tmp;
    			if(cur==flow)	break;
    		}
    	}
    	dep[x]=-1;
    	return cur;
    }
    int dinic()
    {
    	int ans=0;
    	while(bfs())	ans+=dfs(s,inf);
    	return ans;
    }
    int main()
    {
    	int tt,n,m,tot,i;
    	scanf("%d",&tt);
    	while(tt--)
    	{
    		//printf("%d
    ",y)
    		scanf("%d%d",&n,&m);
    		memset(in,0,sizeof(in));
    		memset(ii,0,sizeof(ii));
    		memset(oo,0,sizeof(oo));
    		cnt=1;tot=0;s=n+1;t=s+1;
    		for(i=1;i<=m;i++)
    		{
    			scanf("%d%d%d",&xx[i],&yy[i],&d[i]);
    			oo[xx[i]]++;ii[yy[i]]++;
    			if(!d[i])	add(xx[i],yy[i],1);
    		}
    		for(i=1;i<=n;i++)
    		{
    			if((oo[i]-ii[i])&1)	break;
    			if(oo[i]-ii[i]>0)
    				add(s,i,(oo[i]-ii[i])/2),tot+=(oo[i]-ii[i])/2;
    			else if(oo[i]-ii[i]<0)
    				add(i,t,(ii[i]-oo[i])/2);
    		}
    		if(i<=n)	printf("impossible
    ");
    		else
    		{
    			if(dinic()==tot)	printf("possible
    ");
    			else	printf("impossible
    ");
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    创建用户自定义函数 SQL
    关于“该列没有包含在聚合函数或 GROUP BY 子句中”
    转Oracle性能参数—经典常用
    The server committed a protocol violation. Section=ResponseHeader Detail=CR must be followed by LF 错误
    js定时刷新
    用户获取mac地址的方法
    聚集索引和非聚集索引的区别
    WCF启动报错:“进程不具有此命名空间的访问权限”的解决方法
    利用js文件加载js文件的方法
    C#下载的几种方法
  • 原文地址:https://www.cnblogs.com/hanyuweining/p/10321954.html
Copyright © 2011-2022 走看看