uva 11972 - Round Trip(最大流)

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 Sis 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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值