题意:

  给一个所有你可能想得到的奇葩无向图,要求给每条边定向,使得每个点的入度与出度之差不超过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. 用ScriptEngine在java中和javascript交互的例子(JDK6新特性)

    package demo7; import java.util.Arrays; import java.util.List; import javax.script.Invocable; import ...

  2. POJ 1001 Exponentiation(JAVA,BigDecimal->String)

    题目 计算实数a的n次方,具体输出格式看案例 import java.util.*; import java.math.*; public class Main { public static voi ...

  3. POJ 1759

    Garland Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 1236   Accepted: 547 Descriptio ...

  4. 2015年4月 非常干货之Python资源大全

    [非常干货之Python资源大全]Python是一门美妙的语言,简单易用,容易提升.它是一门主流语言,却没有其它专业语言的弊病,从游戏,ML,GUI到科学和数学有着巨量的函数库. 直击现场 <H ...

  5. Android OpenGL 学习笔记 --开始篇

    转自: http://www.cnblogs.com/TerryBlog/archive/2010/07/09/1774475.html 1.什么是 OpenGL? OpenGL 是个专业的3D程序接 ...

  6. Linux command: usermod -- 改变用户状态

    应用举例: 1. usermod -g newuser newuser force use GROUP as new primary group. 一般时候是默认的,也是必须的(不能更改).2. 指定 ...

  7. jQuery 实验教程

    jQuery 实验教程 jQuery 简介.语法及事件处理 jQuery 以其特有的简练的代码风格,极大得改变了 JavaScript 代码编写的方式.本教程以实例代码为基础,讲解 jQuery 的使 ...

  8. iOS CoreAnimation剖析

    零.前言 这里没有太多的代码细节,只是探索iOS动画的基本概念,以及其抽象模型,数学基础等.我们学习一个知识的时候一般有两个部分,抽象部分和形象部分,抽象好比语言的语法,是规则,形象好比具体的句子,可 ...

  9. 291. Word Pattern II

    题目: Given a pattern and a string str, find if str follows the same pattern. Here follow means a full ...

  10. 机器人学 —— 机器人视觉(Bundle Adjustment)

    今天完成了机器人视觉的所有课程以及作业,确实是受益匪浅啊! 最后一个话题是Bundle Adjustment. 机器人视觉学中,最顶尖的方法. 1.基于非线性优化的相机位姿估计 之前已经在拟合一篇中, ...