首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

[匈牙利+二-sat]hdoj 2444:The Accomodation of Students

2013-11-09 
[匈牙利+2-sat]hdoj 2444:The Accomodation of Students大致题意:? ? 给出一个无向图,判断这个图是不是二

[匈牙利+2-sat]hdoj 2444:The Accomodation of Students

大致题意:

? ? 给出一个无向图,判断这个图是不是二分图,如果不是的话输出“No”。否则输出这个二分图的最大匹配是多少。

?

大致思路:
? ? 首先我们可以先假定图中的点分别属于两个集合,且任何一条边所连接的两点不在一个集合中。将图中的每个点都拆作两个点( i1 和 i2 )分别代表这个点属于第一个集合和这个点属于第二个集合。然后根据上面的逻辑关系,假设i点和j点之间存在边的话则连接i1->j2 i2->j1 j1->i2 j2->i1。得到的图如果不符合2-sat则直接输出“No”。否则,直接对这个二分图求出最大匹配即可。

?

#include<iostream>#include<cstdio>#include <algorithm>#include<cstring>using namespace std;const int inf=1<<30;const int nMax=515;const int mMax=10000000;class edge{public:    int v,nex;};edge e[mMax];int k,head[nMax];//head[i]是以点i为起点的链表头部void addedge(int a,int b){//向图中加边的算法,注意加上的是有向边//b为a的后续节点既是a---->b    e[k].v=b;    e[k].nex=head[a];    head[a]=k;k++;}int dfn[nMax],low[nMax],sta[nMax],top,atype,belon[nMax],dep;   //atype 强连通分量的个数bool insta[nMax];void Tarjan(int u){                 //我的Tarjan模版    int i,j;    dfn[u]=low[u]=++dep;    sta[++top]=u;    insta[u]=1;    for(i=head[u];i;i=e[i].nex){        int v=e[i].v;        if(!dfn[v]){            Tarjan(v);            low[u]=min(low[u],low[v]);        }        else{            if(insta[v])low[u]=min(low[u],dfn[v]);        }    }    if(dfn[u]==low[u]){        atype++;              //强连通分量个数        do{            j=sta[top--];            belon[j]=atype;   //第j个点属于第type个连通块            insta[j]=0;        }while(u!=j);    }}void init(){    k=1;    dep=1;    top=atype=0;    memset(insta,0,sizeof(insta)); //是否在栈中    memset(head,0,sizeof(head));   //静态链表头指针    memset(low,0,sizeof(low));     //Tarjan的low数组    memset(dfn,0,sizeof(dfn));     //Tarjan的dfn数组    memset(belon,0,sizeof(belon)); //记录每个点属于哪一个强连通分量}int n,m,map[nMax][nMax],link[nMax];bool vis[nMax];bool judge(){    for(int i=1;i<=n;i++){        if(belon[i*2]==belon[i*2+1]){            return 0;        }    }    return 1;}int dfs(int s){    for(int i=1;i<=n;i++){        if(!vis[i]&&map[s][i]){            vis[i]=1;            if(link[i]==-1||dfs(link[i])){                link[i]=s;                return 1;            }        }    }    return 0;}int main(){    int i,j,a,b,ans;    while(scanf("%d%d",&n,&m)!=EOF){        init();        ans=0;        memset(map,0,sizeof(map));        while(m--){            scanf("%d%d",&a,&b);            map[a][b]=1;            addedge(a*2,b*2+1);            addedge(a*2+1,b*2);            addedge(b*2+1,a*2);            addedge(b*2,a*2+1);        }        for(i=2;i<=2*n+2;i++){            if(!dfn[i])Tarjan(i);        }        if(!judge()){            printf("No\n");            continue;        }        memset(link,-1,sizeof(link));        for(i=1;i<=n;i++){            memset(vis,0,sizeof(vis));            if(dfs(i))ans++;        }        printf("%d\n",ans);    }    return 0;}
?

热点排行