您的位置:首页 > 理论基础 > 计算机网络

【图论】[Tyvj 1153]间谍网络

2015-07-22 09:06 555 查看
实际上就是先找出整个图里面的强连通分量,然后在每一个强连通子图里面,如果有可以受贿的罪犯,那么当前值就是最小的受贿的代价,否则就是INF, 然后在有向无环图中搞DP就好了。

[code]#include <cstdio>
#include <algorithm>
#include <stack>
#include <iostream>
#include <vector>
#include <cstring>
using namespace std;
const int MAXN = 3000;
const int INF = 1000000000;
const int MAXM = 16000;
struct node{
    int v;
    node *next;
}Edges[MAXM+10], *adj[MAXN+10], *ecnt=Edges, *adj2[MAXN+10];
int kcnt, Min[MAXN+10], Minpeo[MAXN+10], Pid[MAXN+10], spend[MAXN+10], n;
stack<int> sta;
bool insta[MAXN+10];
vector<int> begin;
void addedge(int u, int v){
    ++ecnt;
    ecnt->v = v;
    ecnt->next = adj[u];
    adj[u] = ecnt;
}
void addedge2(int u, int v){
    ++ecnt;
    ecnt->v = v;
    ecnt->next = adj2[u];
    adj2[u] = ecnt;
}
int dfn[MAXN+10], low[MAXN+10], dcnt, tmp;
void dfs1(int u, int fa){
    dfn[u] = low[u] = ++dcnt;
    sta.push(u); insta[u] = true;
    for(node *p=adj[u];p;p=p->next){
        if(!dfn[p->v]){
            dfs1(p->v, u);
            low[u] = min(low[u], low[p->v]);
        }else if(insta[p->v])
            low[u] = min(low[u], dfn[p->v]);
    }
    if(dfn[u] == low[u]){
        ++kcnt;
        Minpeo[kcnt] = INF; Min[kcnt] = INF;
        do{
            tmp = sta.top();
            sta.pop();
            Pid[tmp] = kcnt;
            Min[kcnt] = min(Min[kcnt], spend[tmp]);
            Minpeo[kcnt] = min(Minpeo[kcnt], tmp);
        }while(tmp!=u);
    }
    insta[u] = false;
}
void prepare(){
    for(int i=1;i<=n;i++)
        if(!dfn[i])
            dfs1(i, -1);
    for(int i=1;i<=n;i++)
        for(node *p=adj[i];p;p=p->next)
            if(Pid[p->v] != Pid[i]) 
                addedge2(Pid[i], Pid[p->v]);
}
void dfs2(int u, int _Min){
    for(node *p=adj2[u];p;p=p->next){
        if(Min[p->v] == INF)
            dfs2(p->v, _Min);
        Min[p->v] = 0;
    }
}
void GetAns(){
    //for(int i=1;i<=n;i++) printf("%d-%d\n", i, Pid[i]);
    int Len = begin.size();//for(int i=1;i<=kcnt;i++) printf("%d\n", Min[i]);
    for(int i=0;i<Len;i++)
        dfs2(Pid[begin[i]], Min[Pid[begin[i]]]);
    int Print = INF;
    for(int i=1;i<=kcnt;i++)
        if(Min[i] == INF)
            Print = min(Print, Minpeo[i]);
    if(Print != INF){
        printf("NO\n%d\n", Print);
        return ;
    }
    int sum = 0;
    for(int i=1;i<=kcnt;i++)
        sum += Min[i];
    printf("YES\n%d\n", sum);
}
int main(){
    scanf("%d", &n);
    int r, id, pd;
    scanf("%d", &r);
    for(int i=1;i<=n;i++) spend[i] = INF;
    for(int i=0;i<r;i++){
        scanf("%d%d", &id, &pd);
        spend[id] = pd;
        begin.push_back(id);
    }
    scanf("%d", &r);
    for(int i=0;i<r;i++){
        scanf("%d%d", &id, &pd);
        addedge(id, pd);
    }
    prepare();
    GetAns();

    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: