Random Maze
Time Limit: 10000/3000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 256 Accepted Submission(s): 69
Problem Description
In the game “A Chinese Ghost Story”, there are many random mazes which have some characteristic:
1.There is only one entrance and one exit.
2.All the road in the maze are unidirectional.
3.For the entrance, its out-degree = its in-degree + 1.
4.For the exit, its in-degree = its out-degree + 1.
5.For other node except entrance and exit, its out-degree = its in-degree.
There is an directed graph, your task is removing some edge so that it becomes a random maze. For every edge in the graph, there are two values a and b, if you remove the edge, you should cost b, otherwise cost a.
Now, give you the information of the graph, your task if tell me the minimum cost should pay to make it becomes a random maze.
Input
The first line of the input file is a single integer T.
The rest of the test file contains T blocks.
For each test case, there is a line with four integers, n, m, s and t, means that there are n nodes and m edges, s is the entrance's index, and t is the exit's index. Then m lines follow, each line consists of four integers, u, v, a and b, means that there is an edge from u to v.
2<=n<=100, 1<=m<=2000, 1<=s, t<=n, s != t. 1<=u, v<=n. 1<=a, b<=100000
Output
For each case, if it is impossible to work out the random maze, just output the word “impossible”, otherwise output the minimum cost.(as shown in the sample output)
Sample Input
2
2 1 1 2
2 1 2 3
5 6 1 4
1 2 3 1
2 5 4 5
5 3 2 3
3 2 6 7
2 4 7 6
3 4 10 5
Sample Output
Case 1: impossible
Case 2: 27
Source
The 36th ACM/ICPC Asia Regional Fuzhou Site —— Online Contest
Recommend
lcy
题目: http://acm.hdu.edu.cn/showproblem.php?pid=4067
分析:说到这题不觉有些肉疼,毕竟比赛的时候构图算是对了,就是没判断a,b的大小,然后一直死循环。。。要是A了,这回就能完美7A了,囧
题目给出一张有向图,要求处理起点和终点的所有点满足入度=出度,起点的入度+1=出度,终点的入度=出度+1,其实也就是构造一个欧拉回路?应该是吧。。。然后就是构图
死循环的原因就是出现负环了,因为费用流不能有负环所以只能构图时加判断ab的大小了
1.对于u到v,如果a<=b,就保留那条边,也就是构建一条v到u的边,容量为1,费用为b-a,并且在答案ans上加a,并且u的出度加1,v的入度加1,这条边的意义就是如果这条保留下来的边要删除的话需要b-a的费用,因为咱们是先累加a了
2.对于u到v,如果a>b,就去掉那条边,也就是构建一条u到v的边,容量为1,费用为a-b,并且在答案ans上加b,并且u的入度加1,v的出度加1,这条边的意义就是如果这条删掉的边要恢复的话需要a-b的费用
3.为了保证起点和终点的条件,虚构一条边从终点到起点,也就是起点的出度加1,终点的入度加1,(不能真的把这条边加进图里,因为这是不可改的边)
4.增加源点S和汇点T,如果点I入度大于出度的话就是增加一条边从源点S到点I,容量为入度-出度,费用为0,相反的就是建一条边从点I到汇点T,容量为出度-入度,费用为0
5.求最小费用流,此时最大流如果=到汇点的所有容量之和,就是有解,答案为费用流+ans,否则无解
这题构图还是比较绕的,仔细分析其实很简单。。。
代码:
#include<cstdio>
using namespace std;
const int mm=44444;
const int mn=222;
const int oo=1000000000;
int node,src,dest,edge,ans;
int ver[mm],flow[mm],cost[mm],next[mm];
int head[mn],dis[mn],q[mn],p[mn],in[mn];
bool vis[mn]={0};
inline void prepare(int _node,int _src,int _dest)
{
node=_node,src=_src,dest=_dest;
for(int i=0;i<node;++i)head[i]=-1;
edge=0;
}
inline void addedge(int u,int v,int f,int c)
{
ver[edge]=v,flow[edge]=f,cost[edge]=c,next[edge]=head[u],head[u]=edge++;
ver[edge]=u,flow[edge]=0,cost[edge]=-c,next[edge]=head[v],head[v]=edge++;
}
bool spfa()
{
int i,u,v,l,r=0,tmp;
for(i=0;i<node;++i)dis[i]=oo;
dis[q[r++]=src]=0;
p[src]=p[dest]=-1;
for(l=0;l!=r;(++l==mn)?l=0:1)
for(i=head[u=q[l]],vis[u]=0;i>=0;i=next[i])
if(flow[i]&&dis[v=ver[i]]>(tmp=dis[u]+cost[i]))
{
dis[v]=tmp;
p[v]=i^1;
if(vis[v])continue;
vis[q[r++]=v]=1;
if(r==mn)r=0;
}
return p[dest]>=0;
}
int SpfaFlow()
{
int i,ret=0,delta;
while(spfa())
{
for(i=p[dest],delta=oo;i>=0;i=p[ver[i]])
if(delta>flow[i^1])delta=flow[i^1];
for(i=p[dest];i>=0;i=p[ver[i]])
flow[i]+=delta,flow[i^1]-=delta;
ret+=delta;
ans+=delta*dis[dest];
}
return ret;
}
int main()
{
int u,v,a,b,n,m,s,t,T,sum,cas=0;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&n,&m,&s,&t);
for(u=1;u<=n;++u)in[u]=0;
prepare(n+2,0,n+1);
ans=0;
while(m--)
{
scanf("%d%d%d%d",&u,&v,&a,&b);
if(a<=b)
{
ans+=a;
--in[u],++in[v];
addedge(v,u,1,b-a);
}
else
{
ans+=b;
addedge(u,v,1,a-b);
}
}
--in[t],++in[s];
for(sum=0,u=1;u<=n;++u)
{
if(in[u]>0)addedge(src,u,in[u],0);
if(in[u]<0)addedge(u,dest,-in[u],0),sum-=in[u];
}
if(SpfaFlow()==sum)printf("Case %d: %d\n",++cas,ans);
else printf("Case %d: impossible\n",++cas);
}
return 0;
}