SPOJ IM - Intergalactic Map - [拆点最大流]

题目链接:http://www.spoj.com/problems/IM/en/

Time limit:491 ms  Memory limit:1572864 kB  Code length Limit:50000 B

Jedi knights, Qui-Gon Jinn and his young apprentice Obi-Wan Kenobi, are entrusted by Queen Padmé Amidala to save Naboo from an invasion by the Trade Federation. They must leave Naboo immediately and go to Tatooine to pick up the proof of the Federation’s evil design. They then must proceed on to the Republic’s capital planet Coruscant to produce it in front of the Republic’s Senate. To help them in this endeavor, the queen’s captain provides them with an intergalactic map. This map shows connections between planets not yet blockaded by the Trade Federation. Any pair of planets has at most one connection between them, and all the connections are two-way. To avoid detection by enemy spies, the knights must embark on this adventure without visiting any planet more than once. Can you help them by determining if such a path exists? 
Note - In the attached map, the desired path is shown in bold.

Input Description

The first line of the input is a positive integer t ≤ 20, which is the number of test cases. The descriptions of the test cases follow one after the other. The first line of each test case is a pair of positive integers n, m (separated by a single space). 2 ≤ n ≤ 30011 is the number of planets and m ≤ 50011 is the number of connections between planets. The planets are indexed with integers from 1 to n. The indices of Naboo, Tatooine and Coruscant are 1, 2, 3 respectively. The next m lines contain two integers each, giving pairs of planets that have a connection between them.

Output Description

The output should contain t lines. The ith line corresponds to the ith test case. The output for each test case should be YES if the required path exists and NO otherwise.

Example

Input
2
3 3
1 2
2 3
1 3
3 1
1 3

Output
YES
NO

就是1到n共n个点,互相之间有m条边连接,主人公呢想从1出发,经过2,到达3,不走重复路也不走重复点,问你可不可行。

怎么说呢,最大流构图题做的多了,就有点感觉了,大概知道怎么个建图方向了。

首先,瞟了一眼[网络流建模汇总][Edelweiss].pdf上的思路,知道了从2出发,往1和3两个汇点做最大流,这样就可以满足题目要求;

然后我们就建立超级源点s,和超级汇点t,点2连到s上去,cap=2;点1、3都连到t上去,cap=1;

然后我们还要想到一件事情,不能走重复边,很简单,所有题目里给的边的cap都设为1;

那不走重复点呢?就需要拆点,说起来有点玄乎,其实就是原本是个点,然后我们两只手拿住他,吧唧那么一拉,诶就变成了一条边,

显然,我们就记这条拆点边为( from = in(i) , to = out(i) , cap = 1);

这样我们的图就建好了,剩下来的就是dinic了。

  1 #include<cstdio>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<vector>
  5 #include<queue>
  6 #define INF 0x3f3f3f3f
  7 #define MAXN 2*(30011+1000)
  8 using namespace std;
  9 int n,m;
 10 struct Edge{
 11     int u,v,c,f;
 12 };
 13 struct Dinic
 14 {
 15     int s,t;
 16     vector<Edge> E;
 17     vector<int> G[MAXN];
 18     bool vis[MAXN];
 19     int lev[MAXN];
 20     int cur[MAXN];
 21     void init(int n)
 22     {
 23         E.clear();
 24         for(int i=0;i<=n;i++) G[i].clear();
 25     }
 26     void addedge(int from,int to,int cap)
 27     {
 28         E.push_back((Edge){from,to,cap,0});
 29         E.push_back((Edge){to,from,0,0});
 30         G[from].push_back(E.size()-2);
 31         G[to].push_back(E.size()-1);
 32     }
 33     bool bfs()
 34     {
 35         memset(vis,0,sizeof(vis));
 36         queue<int> q;
 37         q.push(s);
 38         lev[s]=0;
 39         vis[s]=1;
 40         while(!q.empty())
 41         {
 42             int now=q.front(); q.pop();
 43             for(int i=0;i<G[now].size();i++)
 44             {
 45                 Edge edge=E[G[now][i]];
 46                 int nex=edge.v;
 47                 if(!vis[nex] && edge.c>edge.f)
 48                 {
 49                     lev[nex]=lev[now]+1;
 50                     q.push(nex);
 51                     vis[nex]=1;
 52                 }
 53             }
 54         }
 55         return vis[t];
 56     }
 57     int dfs(int now,int aug)
 58     {
 59         if(now==t || aug==0) return aug;
 60         int flow=0,f;
 61         for(int& i=cur[now];i<G[now].size();i++)
 62         {
 63             Edge& edge=E[G[now][i]];
 64             int nex=edge.v;
 65             if(lev[now]+1 == lev[nex] && (f=dfs(nex,min(aug,edge.c-edge.f)))>0)
 66             {
 67                 edge.f+=f;
 68                 E[G[now][i]^1].f-=f;
 69                 flow+=f;
 70                 aug-=f;
 71                 if(!aug) break;
 72             }
 73         }
 74         return flow;
 75     }
 76     int maxflow()
 77     {
 78         int flow=0;
 79         while(bfs())
 80         {
 81             memset(cur,0,sizeof(cur));
 82             flow+=dfs(s,INF);
 83         }
 84         return flow;
 85     }
 86 }dinic;
 87 int in(int x){return x;}
 88 int out(int x){return x+n;}
 89 int main()
 90 {
 91     int t;
 92     scanf("%d",&t);
 93     while(t--)
 94     {
 95         scanf("%d%d",&n,&m);//n个点,m条边
 96         dinic.init(2*n+2);
 97         for(int i=1;i<=m;i++)
 98         {
 99             int from,to;
100             scanf("%d%d",&from,&to);
101             if(1<=from && from<=n && 1<=to && to<=n)
102             {
103                 dinic.addedge(out(from),in(to),1);
104                 dinic.addedge(out(to),in(from),1);
105             }
106         }
107         dinic.s=0, dinic.t=2*n+2;
108         dinic.addedge(dinic.s,in(2),2);
109         dinic.addedge(out(1),dinic.t,1);
110         dinic.addedge(out(3),dinic.t,1);
111         for(int i=1;i<=n;i++) dinic.addedge(in(i),out(i),i==2?2:1);
112         if(dinic.maxflow()==2) printf("YES\n");
113         else printf("NO\n");
114     }
115 }

PS.听说测试输入边的时候,还会超出范围?不管是不是真的,反正加个if()语句鲁棒一下,无所谓。

时间: 2024-10-30 22:11:16

SPOJ IM - Intergalactic Map - [拆点最大流]的相关文章

SPOJ 962 Intergalactic Map (网络最大流)

http://www.spoj.com/problems/IM/ 962. Intergalactic Map Problem code: IM Jedi knights, Qui-Gon Jinn and his young apprentice Obi-Wan Kenobi, are entrusted by Queen Padmé Amidala to save Naboofrom an invasion by the Trade Federation. They must leave N

SPOJ 962 Intergalactic Map

Intergalactic Map Time Limit: 6000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: IM64-bit integer IO format: %lld      Java class name: Main Jedi knights, Qui-Gon Jinn and his young apprentice Obi-Wan Kenobi, are entruste

HDU 2732 Leapin&#39; Lizards(拆点+最大流)

题目意思是有一些蜥蜴在一个迷宫里面,求这些蜥蜴还有多少是无论如何都逃不出来的.题目只给定一个行数n,一个最远能够跳跃的距离d.每只蜥蜴有一个初始的位置,题目保证这些位置都有一些柱子,但是它每离开一根柱子,柱子的高度就会降低1m,问最多能有多少只跳不出去. 将每个柱子在的点进行拆点,把每一个点拆完之后连一条容量为所在点柱子高度的边.从原点连一条容量为1的边,然后找到每个可以直接跳出的点,将这些点与汇点 相连容量为无穷.每个柱子与它可以到达的点的容量也为无穷. Leapin' Lizards Tim

Risk UVA - 12264 拆点法+最大流+二分

/** 题目:Risk UVA - 12264 链接:https://vjudge.net/problem/UVA-12264 题意:给n个点的无权无向图(n<=100),每个点有一个非负数ai. 若ai==0则此点归敌方所有,若ai>0则此点归你且上面有ai个属于你的士兵. 保证至少有一个属于你的点与敌方的点相邻.你可以让你的每个士兵最多移动一次 ,每次可以待在原地或者去到相邻的属于你的领地,但每个点至少要留1各士兵, 使得最薄弱的关口尽量坚固.关口是指与敌方点相邻的点,薄弱与坚固分别指兵少

poj 1698 Alice&#39;s Chance 拆点最大流

将星期拆点,符合条件的连边,最后统计汇点流量是否满就行了,注意结点编号. #include<cstdio> #include<cstring> #include<cmath> #include<iostream> #include<algorithm> #include<set> #include<map> #include<queue> #include<vector> #include<s

HDU 2732 Leapin&amp;#39; Lizards(拆点+最大流)

HDU 2732 Leapin' Lizards 题目链接 题意:有一些蜥蜴在一个迷宫里面,有一个跳跃力表示能跳到多远的柱子,然后每根柱子最多被跳一定次数,求这些蜥蜴还有多少是不管怎样都逃不出来的. 思路:把柱子拆点建图跑最大流就可以,还是挺明显的 代码: #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <algorithm> usin

HDU 2732 Leapin&#39; Lizards(拆点+最大流)

HDU 2732 Leapin' Lizards 题目链接 题意:有一些蜥蜴在一个迷宫里面,有一个跳跃力表示能跳到多远的柱子,然后每根柱子最多被跳一定次数,求这些蜥蜴还有多少是无论如何都逃不出来的. 思路:把柱子拆点建图跑最大流即可,还是挺明显的 代码: #include <cstdio> #include <cstring> #include <cmath> #include <queue> #include <algorithm> using

HDU 2732 Leapin&#39; Lizards(拆点法+最大流)

该题是一道比较简单拆点+最大流的题目,因为每个柱子都有一定的寿命,很容易将其对应成流量,那么处理结点容量的一般方法当然是拆点法 .该题反而对边的容量没有要求,为保险起见可以设成无穷大.   该题的思路很好想,建议独立编写代码 . 推荐题目: 点击打开链接    结点法的一些见解 也可以看这里. 细节参见代码: #include<bits/stdc++.h> using namespace std; typedef long long ll; const int INF = 100000000;

UVAlive--4529--Dangerous Tunnels(二分+拆点最大流)

 Dangerous Tunnels Time Limit: 3000MS   Memory Limit: Unknown   64bit IO Format: %lld & %llu Submit Status Description Somewhere in the world, there are two tribes separated by mountains. The two tribes are named Kulolo and Gulolo, respectively, wh