POJ2186 Popular Cows,Kosaraju算法+缩点

来源:互联网 发布:机器人编程软件dc 编辑:程序博客网 时间:2024/05/07 20:36

算法主要参考这篇解题报告点击打开链接,利用的是Kosaraju算法和缩点,给每个强连通分量染上颜色,缩成点后统计每个点的出度。


/******************************************************************************* # Author : Neo Fung # Email : neosfung@gmail.com # Last modified: 2011-09-23 23:31 # Filename: POJ2186 Popular Cows.cpp # Description : Kosaraju算法+缩节点 ******************************************************************************/// POJ2186 Popular Cows.cpp : Defines the entry point for the console application.//// #include "stdafx.h"// #define DEBUG#include <fstream>#include <stdio.h>#include <iostream>#include <string.h>#include <string>#include <memory.h>#include <stack>#define MAX 10010 using namespace std;struct NODE{int to;NODE *next;}*v[MAX],*rv[MAX],node[10*MAX];int nodecount,n,m;int visit[MAX],color[MAX],sum4clolr[MAX],dag_out[MAX];stack<int> mstack;void init(void){memset(v,'\0',sizeof(v));memset(rv,'\0',sizeof(rv));memset(visit,0,sizeof(visit));memset(color,0,sizeof(color));memset(sum4clolr,0,sizeof(sum4clolr));memset(dag_out,0,sizeof(dag_out));while(!mstack.empty()) mstack.pop();nodecount=0;}void input(void){int from,to;for(int i=0;i<m;++i){scanf("%d %d",&from,&to);node[nodecount].to=to;node[nodecount].next=v[from];v[from]=&node[nodecount++];node[nodecount].to=from;node[nodecount].next=rv[to];rv[to]=&node[nodecount++];}}void DFS(int u)//第一次深度遍历,把遍历结果入栈{visit[u]=1;NODE *head=v[u];while(head){if(!visit[head->to])DFS(head->to);head=head->next;}mstack.push(u);}void DFS_T(int u,int type)//{visit[u]=1;color[u]=type;//给每个节点染色,使得同一个强连通分量都有同一种颜色++sum4clolr[type];//记录下每一种颜色的节点数NODE *head=rv[u];while(head){if(!visit[head->to])DFS_T(head->to,type);head=head->next;}}void kosaraju(void){for(int i=1;i<=n;++i)//第一次DFS搜索所有节点if(!visit[i])DFS(i);memset(visit,0,sizeof(visit));int dagcount=0;while(!mstack.empty())//第二次DFS遍历{int num=mstack.top();mstack.pop();if(!visit[num])DFS_T(num,dagcount++);}//缩点,把每一个强连通分量视为一个点,则整个图成为一个DAG,记录下每个点(即强连通分量)到别的点的出度for(int i=1;i<=n;++i){NODE *head=v[i];while(head){if(color[i]!=color[head->to])//如果点有到别的强连通分量的支路++dag_out[color[i]];head=head->next;}}int index=-1;for(int i=0;i<dagcount;++i)//搜索每一个强连通分量,如果有且只有一个是出度为0的,则强连通分量里的节点数就是结果,否则数据无解if(dag_out[i]==0)if(index==-1)index=sum4clolr[i];else{printf("0\n");return;}if (index==-1)printf("0\n");elseprintf("%d\n",index);}int main(void){#ifdef DEBUG  freopen("data.txt","r",stdin);  #endif  while(scanf("%d %d",&n,&m)!=EOF){init();input();kosaraju();}return 0;}