hdoj 3639 Hawk-and-Chicken

来源:互联网 发布:数据可视化源码下载 编辑:程序博客网 时间:2024/05/16 04:57

类型:连通性

题目: http://acm.hdu.edu.cn/showproblem.php?pid=3639

来源:2010 ACM-ICPC Multi-University Training Contest(19)——Host by HDU

思路:

(1)题目求的是,获得最多支持的人的人,而不是获得最多票的人的人,即每人只能支持其他人一次

(2)联通子图的点可相互到达,将其缩点,构造新图【反向】,点权为强连通分量点的个数,对于每个入度为0的点,求所有能到达它的点权之和,取最大值

(3)vis[]记录已经计算过的点

(4)!!!不能记忆化搜索,dp[u] != 0返回时,其子树的vis并未标记!!! 

// hdoj 3639 Hawk-and-Chicken// wa wa wa ac 250MS 844K#include <iostream>#include <fstream>#include <algorithm>#include <queue>#include <stack>#include <string>#include <cmath>#include <cstring>using namespace std;#define MIN(a,b) ((a) < (b) ? (a) : (b))#define clr(a,b) memset(a, b, sizeof(a))#define FOR(i,a,b) for((i) = (a); (i) < (b); ++(i))#define FORE(i,a,b) for((i) = (a); (i) <= (b); ++(i))#define MAXN 5010#define MAXM 30010const int INF = 0x7f7f7f7f;bool in_stack[MAXN];bool vis[MAXN];int num, cnt, scnt, end_sum, m, n, cnt_num, cases;int in[MAXN];int cnt0[MAXN];int dist[MAXN];int endd[MAXN], endd_num[MAXN];int low[MAXN], step[MAXN];int head[MAXN], shead[MAXN];int belong[MAXN], dp[MAXN];stack<int> st;struct edge {    int v, nxt;}e[MAXM];struct sedge {    int v, nxt;}p[MAXM];void addedge(int u, int v) {    e[cnt].v = v;    e[cnt].nxt = head[u];    head[u] = cnt++;}void addsedge(int u, int v) {    p[scnt].v = v;    p[scnt].nxt = shead[u];    shead[u] = scnt++;}void Tarjan(int u) {    int v;    int i, j;    step[u] = low[u] = ++num;    st.push(u);    in_stack[u] = true;    for(i = head[u]; i != -1; i = e[i].nxt) {        v = e[i].v;        if(!step[v]) {            Tarjan(v);            low[u] = MIN(low[u],low[v]);        }        else if(in_stack[v])            low[u] = MIN(low[u],step[v]);    }    if(step[u] == low[u]) {        cnt_num++;        int tmp_sum = 0;        do{            j = st.top();            st.pop();            in_stack[j] = false;            endd[cnt_num] += 1;            belong[j] = cnt_num;        }while(j != u);    }}void dfs(int u) {    int i, v;//    !!!!!//    if(dp[u] != 0)//        return ;    dp[u] = endd[u];    for(i = shead[u]; i != -1; i = p[i].nxt) {        v = p[i].v;        if(vis[v])            continue;        vis[v] = true;        dfs(v);        dp[u] += dp[v];    }}void solve() {    int i, j;    FOR(i, 0, n)        if(step[i] == 0)            Tarjan(i);    FOR(i, 0, n)        for(j = head[i]; j != -1; j = e[j].nxt)            if(belong[i] != belong[e[j].v]) {                addsedge(belong[e[j].v], belong[i]);                ++in[belong[i]];            }    FORE(i, 1, cnt_num)        if(in[i] == 0) {            clr(vis, false);            dfs(i);            end_sum = max(end_sum, dp[i]);        }    int ccc = 0;    FOR(j, 0, n)        if(dp[belong[j]] == end_sum)            endd_num[ccc++] = j;    printf("Case %d: %d\n", ++cases, end_sum - 1);    FOR(i, 0, ccc)        (i == 0) ? printf("%d", endd_num[i]) : printf(" %d", endd_num[i]);    printf("\n");}void init() {    int i, u, v;    clr(head, -1);    clr(shead, -1);    clr(step, 0);    clr(in, 0);    clr(dp, 0);    clr(belong, 0);    clr(endd, 0);    clr(endd_num, 0);    clr(in_stack, false);    num = cnt = scnt = end_sum = cnt_num = 0;    scanf("%d %d", &n, &m);    FOR(i, 0, m) {        scanf("%d %d", &u, &v);        addedge(u, v);    }}int main() {    int cas;    scanf("%d", &cas);    while(cas--) {        init();        solve();    }    return 0;}/*32 30 10 10 17 70 21 42 42 53 54 65 65 40 12 11 31 4*/