hoj 3005 Game Rigging 强联通分量求缩点
/*
?
題目:
??? 現給出各位選手的能力比較并給出自己的朋友的參賽號碼,如何組織比賽使得自己的朋友能夠獲勝
?
分析:
??? 各選手能力比較可以構造一個有向圖,而想要使得自己的朋友要贏得比賽,所以他的所在的連通塊
??? 必定是入度為0的(假設建圖時是以能力大的人作為邊的起點)。所以題目可以轉換為先建圖,然后
??? 再找連通塊求縮點,然后判斷該縮點是否入度為0,若有朋友在該連通塊中,即可判斷可以組織這樣
??? 的一場比賽。而判斷朋友在不在該連通塊中,可以先求到所有的入度為0的連通塊用數組置為true,
??? 然后直接把所有朋友的所在的連通塊置為false,若所有的連通塊中只要還有true的連通塊,就可判斷
??? 不能組織這樣的一場比賽
?
*/
#include <cstdio>
#include <cstring>
?
const int X = 100005;
?
int dfn[X],low[X],stack[X],deg[X],father[X],depth,top,bcnt;
int f[X],fri,n,m;
bool use[X],instack[X];
?
struct node
{
??? int v;
??? node *next;
??? void fun()
??? {
??????? v = 0;
??????? next = NULL;
??? }
}edge[X],*head[X],*tmp;
?
void tarjan(int u)
{
??? int v;
??? dfn[u] = low[u] = ++depth;
??? stack[++top] = u;
??? instack[u] = true;
?
??? for(node *p=head[u];p;p=p->next)
??? {
??????? v = p->v;
??????? if(!low[v])
??????? {
??????????? tarjan(v);
??????????? if(low[v]<low[u])
??????????????? low[u] = low[v];
??????? }
??????? else if(instack[v]&&low[u]>dfn[v])
? ??????????low[u] = dfn[v];
??? }
??? if(low[u]==dfn[u])
??? {
??????? bcnt++;
??????? do
??????? {
??????????? v = stack[top--];
??????????? instack[v] = false;
??????????? father[v] = bcnt;
??????? }while(u!=v);
??? }
}
?
void solve()
{
??? memset(instack,false,sizeof(instack));
??? memset(low,0,sizeof(low));
??? memset(deg,0,sizeof(deg));
??? depth = bcnt = top = 0;
?
??? for(int i=1;i<=n;i++)
??????? if(!low[i])
??????????? tarjan(i);
?
??? for(int i=1;i<=n;i++)
??????? for(node *p=head[i];p;p=p->next)
??????????? if(father[i]!=father[p->v])
??????????????? deg[father[p->v]]++;
?
??? memset(use,false,sizeof(use));
??? for(int i=1;i<=bcnt;i++)
??????? if(!deg[i])
??????????? use[i] = true;
?
??? for(int i=0;i<fri;i++)
??????? use[father[f[i]]] = false;
?
??? bool flag = true;
??? for(int i=1;i<=bcnt;i++)
??????? if(use[i])
??????? {
??????????? flag = false;
??????????? break;
??????? }
??? flag?printf("yes\n"):printf("no\n");
}
?
int main()
{
??? freopen("sum.in","r",stdin);
??? freopen("sum.out","w",stdout);
??? while(scanf("%d%d%d",&n,&fri,&m),n||m||fri)
??? {
??????? for(int i=0;i<fri;i++)
??????????? scanf("%d",&f[i]);
??????? memset(head,NULL,sizeof(head));
?
??????? for(int i=0;i<m;i++)
??????????? edge[i].fun();
??????? tmp = edge;
??????? int u,v;
??????? for(int i=0;i<m;i++)
??????? {
??????????? scanf("%d%d",&u,&v);
??????????? tmp->next = head[u];
??????????? tmp->v = v;
??????????? head[u] = tmp++;
??????? }
??????? solve();
??? }
?
??? return 0;
}
轉載于:https://www.cnblogs.com/yejinru/archive/2012/05/18/2507973.html
總結
以上是生活随笔為你收集整理的hoj 3005 Game Rigging 强联通分量求缩点的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Windows Phone 网络Http
- 下一篇: [转载]读塔莎奶奶的美好生活