1. 程式人生 > >洛谷1262 間諜網路 tarjan縮點

洛谷1262 間諜網路 tarjan縮點

這個題首先tarjan縮個點,然後統計各個縮完之後的點的中被收買人的最小值,假如某個強連通分量的入度為0,那就收買他,我實在是太蒟蒻了想了半天怎麼判斷NO的情況想不通一直卡在92,後來看了題解恍然大悟。假如一個人不能被收買,那我就直接在targin的時候不搜這個點,那麼之後遍歷一遍dfn,如果存在0,就說明有一個人既不能被舉報,也不能被收買,輸出NO和編號即可。附上程式碼:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
int s[100001]={0},low[100001]={0},dfn[100001]={0},co[100001]={0},buy[100001]={0},d1[100001]={0};
int x[100001]={0},y[100001]={0},nxt[100001]={0},head[100001]={0},to[100001]={0},min1[100001]={0},d2[100001]={0};
int tmp=0,num=0,top=0,col=0,n,p,r;
int min(int x,int y)
{
    if(x>y)
      return y;
    else return x;
}
int add(int x,int y)
{
    tmp++;
    to[tmp]=y;
    nxt[tmp]=head[x];
    head[x]=tmp;
    return 0;
}
int tarjan(int i)
{
    int j,t;
    num++;top++;
    s[top]=i;low[i]=num;dfn[i]=num;
    for(j=head[i];j;j=nxt[j])
      {
      t=to[j];
      if(dfn[t]==0)
        {
        tarjan(t);
        low[i]=min(low[i],low[t]);
        }
      else if(co[t]==0)
        {
        low[i]=min(low[i],low[t]);
        }
      }
    if(dfn[i]==low[i])
      {
      col++;
      co[i]=col;
      if(buy[i]!=0)
        min1[col]=buy[i];
      while(s[top]!=i)
        {
        co[s[top]]=col;
        if(buy[s[top]]!=0)
          min1[col]=min(min1[col],buy[s[top]]);
        top--;
        }
      top--;
      }
    return 0;
}
int main()
{
    int i,j,ans=0,u,t;
    scanf("%d%d",&n,&p);
    for(i=1;i<=5000;i++)
      min1[i]=1000000;
    for(i=1;i<=p;i++)
      {
      scanf("%d",&u);
      scanf("%d",&buy[u]);
      }
    scanf("%d",&r);
    for(i=1;i<=r;i++)
      {
      scanf("%d%d",&x[i],&y[i]);
      add(x[i],y[i]);
      }
    for(i=1;i<=n;i++)
      if(dfn[i]==0&&buy[i]!=0)
        tarjan(i);
    for(i=1;i<=n;i++)
      if(dfn[i]==0)
        {
        printf("NO\n%d",i);
        return 0;
        }
    memset(head,0,sizeof(head));
    memset(to,0,sizeof(to));
    memset(nxt,0,sizeof(nxt));
    tmp=0;
    for(i=1;i<=r;i++)
      if(co[x[i]]!=co[y[i]])
        {
        add(co[x[i]],co[y[i]]);
        }
    for(i=1;i<=col;i++)
      {
      for(j=head[i];j;j=nxt[j])
        {
        t=to[j];
        d1[i]++;d2[t]++;
        }
      }
    for(i=1;i<=col;i++)
      if(d2[i]==0)
        ans+=min1[i];
    printf("YES\n");
    printf("%d",ans);
    return 0;
}