好吧~圖論的學習該告一段落了。這個題很有意思:
說有幾個學校,相互傳遞盜版軟體,為單向傳遞關係。問給最少幾個學校盜版軟體,可以使得全部的學校都有盜版軟體。2問最少添加幾個傳遞關係,使得不論城管消滅其中的一條傳遞線路,還是能夠讓所有的學校都通過一張盜版光碟片傳遞完。
思路呢.... 很簡單,對圖中的強連通分量進行縮點,形成圖G‘,這樣去找入度為0的連通分量數即可。因為沒有盜版軟體必須要有源頭,而如度為0的強連通分量沒有源頭,故發軟體。
2.出度為零的連通分量和入度為零的強連通分量中值最大的即為答案。因為要連成環就不怕城管了,所以入度和出度為零的連邊就好了~
求解強連通分量比較熟悉了~ 很快的寫代碼1Y
#include<iostream>#include<stack>#define MAXN 105using namespace std;struct Node{ int v; Node *next;}Edge[MAXN*MAXN],*ptr[MAXN];Node Edge2[MAXN];Node *ptr2[MAXN];int DFN[MAXN],LOW[MAXN];int DEP,SCCNum;int N,Point[MAXN];bool inS[MAXN];int min( int a,int b ){ return a<b?a:b; }void addEdge( int u,int v ){ Node *p=&Edge[++DEP]; p->v=v; p->next=ptr[u]; ptr[u]=p;}void addEdge2( int u,int v ){ Node *p=&Edge2[++DEP]; p->v=v; p->next=ptr2[u]; ptr2[u]=p;}stack<int>myStack;void Tarjan( int u ){ myStack.push(u); inS[u]=true; DFN[u]=LOW[u]=++DEP; Node *p=ptr[u]; while( p ) { if( DFN[p->v]==0 ) { Tarjan( p->v ); LOW[u]=min( LOW[u],LOW[p->v]); } else if( inS[p->v] ) LOW[u]=min(LOW[u],DFN[p->v] ); p=p->next; } if( DFN[u]==LOW[u] ) { int v; ++SCCNum; do { v=myStack.top(); myStack.pop(); inS[v]=0; Point[v]=SCCNum; }while( u!=v ); }}int main(){ while( scanf( "%d",&N )!=EOF ) { memset( DFN,0,sizeof(DFN) ); memset( LOW,0,sizeof(LOW) ); memset( inS,0,sizeof(inS) ); memset( Point,0,sizeof(Point) ); SCCNum=0; int i,j; for( i=0;i<=N;i++ ) ptr[i]=ptr2[i]=NULL; DEP=0; for( i=1;i<=N;i++ ) { while( true ){ scanf( "%d",&j ); if( j==0 ) break; addEdge( i,j ); } } DEP=0; for( i=1;i<=N;i++ ) if( DFN[i]==0 ) Tarjan( i ); DEP=0; for( i=1;i<=N;i++ ) { Node *p=ptr[i]; while( p ) { if( Point[i]!=Point[p->v] ) addEdge2( Point[i],Point[p->v] ); p=p->next; } } int inD[MAXN],outD[MAXN]; memset( inD,0,sizeof(inD) ); memset( outD,0,sizeof(outD) ); for( i=1;i<=SCCNum;i++ ) { Node *p=ptr2[i]; while( p ) { outD[i]++; inD[p->v]++; p=p->next; } } int cntI,cntO; cntI=cntO=0; //printf( "%d\n",SCCNum ); for( i=1;i<=SCCNum;i++ ) { if( inD[i]==0 ) cntI++; if( outD[i]==0 ) cntO++; } printf( "%d\n",cntI ); if( SCCNum==1 ) printf( "0\n" ); else printf( "%d\n",cntI>cntO?cntI:cntO ); } return 0;}