V
— Round Trip
Time Limit: 1 sec
Memory Limit: 32 MB
John recently has had his birthday party. As John likes traveling, all invited guests cooperated and decided to buy various tickets as a present. Each ticket can be used only once to travel from some city A to city B or vice versa. As guests were cooperating, they decided that no tickets will be between the same cities.
Now John has huge amount of tickets and needs to plan his trip. But first, he wishes to know the cities that now he can possibly visit and come back home. In other words you have to find all cities John can visit by making a round trip from the home city through that particular city.
INPUT
The number of tests T
(T ≤ 100) is given on the first line. Each test starts with 3 integers N M C
(N ≤ 100; M ≤ 1000; 1 ≤ C ≤ N). Where N
stands for number of cities (cities are numbered from 1
to N
) and M
is number of tickets John has. C
describes his living city number. Next M
lines describe tickets with 2 integers X Y
(1 ≤ T ≤ 100). X
and Y
are cities on the ticket.
OUTPUT
For each test case output a single line "Case T: S"
. Where T
is the test case number (starting from 1) and S
is single space separated list of cities that John could possibly visit. This list must be sorted in increasing order. If John can’t find a single city to visit print "none"
intead ( i.e. Case 2: none
).
SAMPLE INPUT
2 6 7 1 1 2 1 3 2 6 4 6 2 5 5 3 4 2 2 1 2 1 2
SAMPLE OUTPUT
Case 1: 2 3 4 5 6 Case 2: none
Problem by: Aleksej Viktorchik; Leonid Sislo
Huge Easy Contest #2
在一个无向图上,问从某个点出发,找一条回路,每条边只能经过一次,有哪些点可能在回路上。每条边只能经过一次,看到这个就有种流的感觉。想到枚举所有的点,判断它是否可能在回路上。判断就成了无向图上,从起点出发,到某个点的最大流是不是大于等于2(说明存在环)。无向图的最大流,就是把原来的无向边,替换成正反两个方向,容量一样的有向边。n的范围是100,所以最大流还是可能会超时的,没管那么多,大胆一试过了。
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <queue>
#include <iostream>
#include <stack>
#include <set>
#include <cstring>
#include <stdlib.h>
#include <cmath>
using namespace std;
typedef long long LL;
typedef pair<int, int> P;
const int maxn = 100 + 5;
const int INF = 1000000000;
struct Edge {
int from, to, cap, flow;
};
struct Dinic {
int n, m, s, t;
vector<Edge> edges; // 边数的两倍
vector<int> G[maxn]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号
bool vis[maxn]; // BFS使用
int d[maxn]; // 从起点到i的距离
int cur[maxn]; // 当前弧指针
void ClearAll(int n) {
for(int i = 0; i < n; i++) G[i].clear();
edges.clear();
}
void ClearFlow() {
for(int i = 0; i < edges.size(); i++) edges[i].flow = 0;
}
void AddEdge(int from, int to, int cap) {
edges.push_back((Edge){from, to, cap, 0});
edges.push_back((Edge){to, from, 0, 0});
m = edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BFS() {
memset(vis, 0, sizeof(vis));
queue<int> Q;
Q.push(s);
vis[s] = 1;
d[s] = 0;
while(!Q.empty()) {
int x = Q.front(); Q.pop();
for(int i = 0; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]];
if(!vis[e.to] && e.cap > e.flow) {
vis[e.to] = 1;
d[e.to] = d[x] + 1;
Q.push(e.to);
}
}
}
return vis[t];
}
int DFS(int x, int a) {
if(x == t || a == 0) return a;
int flow = 0, f;
for(int& i = cur[x]; i < G[x].size(); i++) {
Edge& e = edges[G[x][i]];
if(d[x] + 1 == d[e.to] && (f = DFS(e.to, min(a, e.cap-e.flow))) > 0) {
e.flow += f;
edges[G[x][i]^1].flow -= f;
flow += f;
a -= f;
if(a == 0) break;
}
}
return flow;
}
int Maxflow(int s, int t) {
this->s = s; this->t = t;
int flow = 0;
while(BFS()) {
memset(cur, 0, sizeof(cur));
flow += DFS(s, INF);
}
return flow;
}
};
Dinic g;
vector<int> ans;
int main(){
int t, kase = 0;
scanf("%d", &t);
while(t--){
kase++;
int n, m, c;
scanf("%d%d%d", &n, &m, &c);
c--;
g.ClearAll(n);
while(m--){
int x, y;
scanf("%d%d", &x, &y);
x--;y--;
g.AddEdge(x, y, 1);
g.AddEdge(y, x, 1);
}
ans.clear();
for(int i = 0;i < n;i++){
if(i == c) continue;
g.ClearFlow();
if(g.Maxflow(c, i) >= 2) ans.push_back(i+1);
}
printf("Case %d: ", kase);
if(ans.size() == 0) printf("none\n");
else{
for(int i = 0;i < ans.size()-1;i++){
printf("%d ", ans[i]);
}
printf("%d\n", ans[ans.size()-1]);
}
}
return 0;
}