hdu 2767 Proving Equivalences

来源:互联网 发布:手机数据备份与恢复 编辑:程序博客网 时间:2024/06/06 15:42

题目链接点这里


读完提应该就知道是要把一个有向图,加几条边,使得整个图强连通,求最少要加几条边,恩。

先把强连通分量缩点,然后大胆证明(xjb猜测)+仔细观察,可以想到,,貌似和入肚和初度有关,,,大概等于max(入肚为0的分量,初度为0的分量)

#include<iostream>#include<map>#include<stdio.h>#include<bitset>#include<stack>#include<algorithm>#include<queue>#include<set>#include<string.h>#include<string>#include<vector>#define MX 22222#define INF 0x3f3f3f3f#define mem(x,y) memset(x,y,sizeof(x))#define FIN freopen("input.txt","r",stdin)using namespace std;int n,m;int head[MX],cnt;struct Edge {    int nxt,to;} edge[3*MX];void edge_init() {    mem(head,-1);    cnt=0;}void edge_add(int a,int b) {    edge[cnt].to=b;    edge[cnt].nxt=head[a];    head[a]=cnt++;}int low[MX],pre[MX],sccno[MX],dfs_block,scc_cnt;stack<int> S;void dfs(int u) {    low[u]=pre[u]=++dfs_block;    S.push(u);    for(int i=head[u]; ~i; i=edge[i].nxt) {        int v=edge[i].to;        if(!pre[v]) {            dfs(v);            low[u]=min(low[u],low[v]);        } else if(!sccno[v]) {            low[u]=min(low[u],pre[v]);        }    }    if(pre[u]==low[u]) {        scc_cnt++;        while(1) {            int w=S.top();            S.pop();            sccno[w]=scc_cnt;            if(w==u) break;        }    }}void find_scc() {    dfs_block=scc_cnt=0;    mem(pre,0);    mem(low,0);    mem(sccno,0);    for(int i=1; i<=n; i++)        if(!pre[i]) dfs(i);}bool in[MX],out[MX];int main() {    FIN;    int t;    scanf("%d",&t);    while(t--) {        scanf("%d%d",&n,&m);        edge_init();        for(int i=1; i<=m; i++) {            int a,b;            scanf("%d%d",&a,&b);            edge_add(a,b);        }        find_scc();        // cout<<"scc"<<scc_cnt<<endl;        if(scc_cnt==1) {            puts("0");        } else {            mem(in,0);            mem(out,0);            for(int i=1; i<=n; i++) {                for(int j=head[i]; ~j; j=edge[j].nxt) {                    if(sccno[i]!=sccno[edge[j].to]) {                        in[sccno[edge[j].to]]=1;                        out[sccno[i]]=1;                    }                }            }            int cnt1=0,cnt2=0;            for(int i=1; i<=scc_cnt; i++) {                if(!in[i]) cnt1++;                if(!out[i]) cnt2++;            }            printf("%d\n",max(cnt1,cnt2));        }    }    return 0;}


0 0
原创粉丝点击