题意:

  给一个所有你可能想得到的奇葩无向图,要求给每条边定向,使得每个点的入度与出度之差不超过1。输出1表示定向往右,输出0表示定向往左。

思路:

  网络流也是可以解决的!!应该挺简单理解的。但是由于复杂度的问题,EK和Dinic都搞不定,ISAP才行。

  利用欧拉回路的思想。既然每个点的入度与出度之差不超过1,那么在每两个奇数度的点添加1条无向边并不会影响到什么。那么先添加一些边进去,使得所有点的度都是偶数的。先随意帮每条边定个方向,进行建新图(用于跑最大流),假设u->v,那么u的出度就是可以给v的(当且仅当这条边反转时),建边u->v,容量为1。添加超级源点s连接到所有【出度大于入度的点】,容量为(出度-入度)/2,表示它有这么多个出度可以赠人。将所有【入度大于出度的点】连一条边到超级汇点t,容量为(入度-出度)/2,表示需要这么多的入度。接着跑一遍最大流(结果必定是满流的,即所有点的出度=入度),每条有流的边就需要将原来随意定下的方向反过来。参考

 #include <bits/stdc++.h>
#define INF 0x7f7f7f7f
#define pii pair<int,int>
#define LL long long
using namespace std;
const int N=;
struct node
{
int from, to, cap, flow, has;
node(){};
node(int from, int to,int cap,int flow,int has):from(from),to(to),cap(cap),flow(flow),has(has){};
}edge[N*];
int chu[N], ru[N], vis1[N], ans[N*], edge_cnt;
vector<int> vect[N], rev[N], md; //图的反向边在这,反向BFS时用的。
vector<pii> g; void init(int up)
{
md.clear();
g.clear();
memset(chu,,sizeof(chu));
memset(ru, ,sizeof(ru));
edge_cnt=;
for(int i=; i<=up; i++) vect[i].clear(),rev[i].clear();
} void add_node(int from,int to,int cap,int flow,int has)
{
edge[edge_cnt]=node(from, to, cap, flow, has);
rev[to].push_back(edge_cnt); //反向,用于ISAP的BFS
vect[from].push_back(edge_cnt++);
} void change() //修改原来定下方向的边
{
for(int i=; i<edge_cnt; i++)
{
node e=edge[i];
if( e.has>= && e.flow> ) ans[e.has]= -ans[e.has];
}
} bool isok(int n) //判断是否已经满足要求
{
for(int j=; j<=n; j++) if( abs(chu[j]-ru[j])> ) return false;
return true;
} int num[N], p[N], d[N], cur[N], vis[N]; //最大流用的
deque<int> que;
void BFS(int s,int e) //模板
{
memset(vis, , sizeof(vis));
que.clear();
que.push_back(e);
vis[e]=;
d[e]=;
num[]=; //gap可以在这更新 while(!que.empty())
{
int x=que.front();que.pop_front();
for(int i=; i<rev[x].size(); i++)
{
node e=edge[rev[x][i]];
if(!vis[e.from])
{
vis[e.from]=;
d[e.from]=d[e.to]+;
++num[d[e.from]];
que.push_back(e.from);
}
}
}
} int Augment(int s,int e) //模板
{
int ed=e, big=INF;
while(ed!=s)
{
node &e=edge[p[ed]];
big=min(big, e.cap-e.flow);
ed=edge[p[ed]].from;
}
ed=e;
while(ed!=s)
{
edge[p[ed]].flow+=big;
edge[p[ed]^].flow-=big;
ed=edge[p[ed]].from;
}
return big; //找到的流
} int max_flow(int n, int s, int e) //最大流模板
{
int ans_flow=;
memset(num, , sizeof(num));
BFS(s, e); //更新d数组
int x=s;
memset(cur, ,sizeof(cur));
while(d[s]<n)
{
if(x==e)
{
ans_flow+=Augment(s,e);
x=s;
}
int ok=;
for(int i=cur[x]; i<vect[x].size(); i++)
{
node &e=edge[vect[x][i]];
if(e.cap>e.flow && d[x]==d[e.to]+)
{
ok=;
p[e.to]=vect[x][i]; //记录边号
cur[x]=i;
x=e.to;
break;
}
}
if(!ok)
{
int m=n-;
for(int i=; i<vect[x].size(); i++)
{
node e=edge[vect[x][i]];
if(e.cap>e.flow) m=min(m, d[e.to]);
}
if(--num[d[x]]==) break;
d[x]=m+;
num[d[x]]++;
cur[x]=;
if(x!=s) x=edge[p[x]].from;
}
}
return ans_flow;
} int cal(int n, int s, int e)
{
if(isok(n)) return ; //已经满足要求了,不用跑最大流
int mcnt=g.size(), ncnt=;; //奇数度的点需要补边
md.clear();
for(int i=; i<=n; i++) if((chu[i]+ru[i])&) md.push_back(i);
for(int i=; i<md.size(); i+=)
{
g.push_back(make_pair(md[i],md[i+]));
chu[md[i]]++, ru[md[i+]]++;
} //建图***************
memset(vis1,,sizeof(vis1));
for(int i=; i<g.size(); i++)
{
int a=g[i].first;
int b=g[i].second;
int h= i<mcnt? i: -; if(!vis1[a]) ncnt++; //统计新图中的点数
if(!vis1[b]) ncnt++; add_node(a, b, , , h); //这是给定的边
add_node(b, a, , , -); if(!vis1[a]&&chu[a]>ru[a]) //添加源点
{
vis1[a]=;
int cnt=(chu[a]-ru[a])/;
add_node(, a, cnt, , -);
add_node(a, , , , -); }
if(!vis1[b]&&ru[b]>chu[b]) //添加汇点
{
vis1[b]=;
int cnt=(ru[b]-chu[b])/;
add_node(b, n+, cnt, , -);
add_node(n+, b, , , -);
}
} //最大流************
max_flow(ncnt+, s, e); //ncnt+2是表示点数 //修改一下答案******
change();
} int main()
{
freopen("input.txt", "r", stdin);
int t, n, m, a, b;
cin>>t;
while(t--)
{
scanf("%d%d",&n,&m);
init(n+);
for(int i=; i<m; i++)
{
scanf("%d %d", &a, &b);
chu[a]++, ru[b]++;
ans[i]=;
g.push_back(make_pair(a,b));
}
cal(n, , n+);
for(int i=; i<m; i++) printf("%d\n",ans[i]);
}
return ;
}

AC代码

附送个数据产生程序(跑完最大流后再测试一下是否满足要求了):

 #include <bits/stdc++.h>
#define INF 0x7f7f7f7f
#define pii pair<int,int>
#define LL long long
using namespace std;
const int N=; int main()
{
freopen("output.txt", "w+", stdout);
int t=;//例子数
int a, b;
puts("");
srand(time());
while(t--)
{
a=((int)rand())%+;//点数
b=((int)rand())%min((a*a),)+;//边数
printf("\n\n%d %d\n\n", a, b); for(int i=; i<b; i++)
{
int u=((int)rand())%a+;
int v=((int)rand())%a+;
printf("%d %d\n",u,v);
}
}
return ;
}

数据产生器

HDU 5348 MZL's endless loop 给边定向(欧拉回路,最大流)的更多相关文章

  1. Hdu 5348 MZL's endless loop (dfs)

    题目链接: Hdu 5348 MZL's endless loop 题目描述: 给出一个无向图(有环,有重边),包含n个顶点,m条边,问能否给m条边指定方向,使每个顶点都满足abs(出度-入度)< ...

  2. 2015 Multi-University Training Contest 5 hdu 5348 MZL's endless loop

    MZL's endless loop Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Oth ...

  3. HDU 5348 MZL's endless loop(DFS去奇数度点+欧拉回路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5348 题目大意:给你一张图,有n个点,和m条无向边,让你把m条无向边变成有向边,使得每个节点的|出度- ...

  4. HDU 5348 MZL's endless loop

    乱搞题...第一直觉是混合图的欧拉通路,但是感觉并没有多大关系.最终AC的做法是不断的寻找欧拉通路,然后给边标号.所有边访问了一遍,所有点访问了一遍,效率是o(n+m).不存在-1的情况. #incl ...

  5. 图论 HDOJ 5348 MZL's endless loop

    题目传送门 /* 题意:给一个n个点,m条边的无向图,要求给m条边定方向,使得每个定点的出入度之差的绝对值小于等于1. 输出任意一种结果 图论:一个图,必定存在偶数个奇度顶点.那么从一个奇度定点深搜, ...

  6. 2015多校.MZL's endless loop(欧拉回路的机智应用 || 构造)

    MZL's endless loop Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Oth ...

  7. hdu5348 MZL's endless loop(欧拉回路)

    转载请注明出处: http://www.cnblogs.com/fraud/          ——by fraud MZL's endless loop Time Limit: 3000/1500 ...

  8. hdu 5348 MZL&#39;s endless loop

    给一个无向图(事实上是有向的.可是没有指定边的方向),你须要指定边的方向,使得每一个点入度和出度相差不超过1. 事实上就是找很多条路径.合起来能走完这个图..先统计各个顶点的度.度为奇数必是起点或终点 ...

  9. [2015hdu多校联赛补题]hdu5348 MZL's endless loop

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5348 题意:给你一个无向图,要你将无向图的边变成有向边,使得得到的图,出度和入度差的绝对值小于等于1, ...

随机推荐

  1. SQL技术内幕-7 varchar类型的数字和 int 类型的数字的比较+cast的适用

    DECLARE @x VARCHAR(10); DECLARE @y INT; DECLARE @z VARCHAR(10); SET @x = '1000'; SET @y = '2000'; SE ...

  2. shell如何自动输入密码

    shell如何自动输入密码 http://linux.ctocio.com.cn/171/12162171.shtml

  3. UVA 11481 - Arrange the Numbers 数学

    Consider this sequence {1, 2, 3, . . . , N}, as a initial sequence of first N natural numbers. You ca ...

  4. JDK环境变量解析

    设置环境变量 在java 中需要设置三个环境变量(1.5之后不用再设置classpath了,但个人强烈建议继续设置以保证向下兼用问题)JDK安装完成之后我们来设置环境变量:右击“我的电脑”,选择“属性 ...

  5. C#产生不重复的随机数并生成随机文件名

    本文转自:http://blog.ciznx.com/post/csharprandomnumberandrandomfilename.aspx 在项目中会遇到需要批量生成文件的时候,比如 asp.n ...

  6. installation failed with message null

    http://stackoverflow.com/questions/33315753/installation-failed-with-message-null-genymotion-error I ...

  7. android listview 加载图片错乱(错位)

       写道 今天晚上一个朋友介绍我看了一篇文章,也是解决android中listview在加载图片错位的问题,看了之后,感觉写的很好,自己也遇到这个问题,但是又不知道从何下手,看到这篇文章后,我的问题 ...

  8. ruby libmysqlclient.18.dylib

    在mac 的rails环境中,如果已经确定安装了 mysql server,但是在启动rails s (服务器)的时候出现  Library not loaded: libmysqlclient.18 ...

  9. java基本数据类型存储范围

    数据类型可以分为两大类: 1)基本类型: 2)扩展类型. 先来看一下Java语言的基本数据类型.它包括 类型    描述   取值范围 Boolean 布尔型 只有两个值true.false Char ...

  10. Struts2笔记——struts常用标签

    使用struts标签前,首先要配置struts2架构,然后导入标签库,jsp插入如下语句: <%@taglib uri="/struts-tags" prefix=" ...