CCF——高速公路

分享该博主的博客: http://blog.csdn.net/lishuhuakai/article/details/50346129

附上别处引用的代码:

#include "Stdafx.h"
#include <iostream>
#include <stack>
using namespace std;

#define MAX_VERTEX_SIZE 10001
struct EdgeNode{
    int vertex;
    EdgeNode *nextArc;
};

struct VerTexNode{
    EdgeNode* firstArc;
};

struct Graph{
    int n,e;
    VerTexNode vNode[MAX_VERTEX_SIZE];
};

int time = 0;
int low[MAX_VERTEX_SIZE];
int dfn[MAX_VERTEX_SIZE];
int visited[MAX_VERTEX_SIZE];
int inStack[MAX_VERTEX_SIZE];
int ans = 0;//存储运算结果
stack<int> st;
Graph graph;

void initeGraph(int n,int m)
{
    for(int i = 1;i<=n;i++)
    {
        graph.vNode[i].firstArc = NULL;
    }
    graph.n = n;
    graph.e = m;

}

//头插法建立图
void creatGraph(int s,int v)
{
    EdgeNode *edgeNode = new EdgeNode;
    edgeNode->vertex = v;
    edgeNode->nextArc = graph.vNode[s].firstArc;
    graph.vNode[s].firstArc = edgeNode;
}    

int min(int a,int b)
{
    if(a>b)
        return b;
    else
        return a;
}

void trajan(int u)
{
    dfn[u] = low[u] = time++;
    st.push(u);
    visited[u] = 1;
    inStack[u] = 1;
    EdgeNode *edgePtr = graph.vNode[u].firstArc;
    while(edgePtr !=NULL)
    {
        int v = edgePtr->vertex;
        if(visited[v] == 0)
        {
            trajan(v);
            low[u] = min(low[u],low[v]);
        }
        /*之前没有对inStack[v]进行判断,又可能当前的v已经出栈了,这个时候就会出错。
        所以导致我的最后得分为80分。
        加上if条件,最后为满分。
        切记!切记!切记!!!
        */

        else if(inStack[v] == 1)
        {
            low[u] = min(low[u],dfn[v]);
        }
        edgePtr = edgePtr->nextArc;
    }

    int result = 0;
    if(dfn[u] == low[u])
    {
        int vtx;
        //cout<<"set is: ";
        do{
            result++;
            vtx = st.top();
            st.pop();
            inStack[vtx] = 0;//表示已经出栈
        /*    cout<<vtx<<' ';*/
        }while(vtx !=u );
        if(result > 1)
        {
            ans += result*(result-1)/2;
        }
        result = 0;
    }

}

int main()
{
    int n,m;
    int s,a;
    cin>>n>>m;
    initeGraph(n,m);
    for(int i = 1;i<=n;i++)
    {
        visited[i] = 0;
        inStack[i] = 0;
        dfn[i] = 0;
        low[i] = 0;
    }

    for(int j = 1;j<=m;j++)
    {
        cin>>s>>a;
        creatGraph(s,a);
    }

    for(int i =1;i<=n;i++)
        if(visited[i] == 0)
            trajan(i);
    cout<<ans<<endl;
    return 0;
}
#include<iostream>  
 using namespace std;  
 #include<string.h>  
 #include<algorithm>  
 int n,m;  
 int head[10010],stackn[10010],DFN[10010],Low[10010];  
 int Belong[10010],instack[10010],cnt,top,f,scnt;  
 struct node  
 {  
     int e,next;  
 }edge[100010];  
 void add(int s,int e)  
 {  
     edge[f].e=e;  
     edge[f].next=head[s];  
     head[s]=f++;  
 }  
 void tarjan(int s)  
 {  
     int t,k,i;  
     DFN[s]=Low[s]=++cnt;  
     stackn[top++]=s;  
     instack[s]=1;  
     for(i=head[s];i!=-1;i=edge[i].next)  
     {  
         k=edge[i].e;  
         if(!DFN[k])  
         {  
             tarjan(k);  
             Low[s]=min(Low[k],Low[s]);  
         }  
         else if(instack[k])  
         {  
             Low[s]=min(Low[s],DFN[k]);  
         }  
     }  
     if(Low[s]==DFN[s])  
     {  
         scnt++;  
         do  
         {  
             t=stackn[--top];  
             Belong[t]=scnt;  
             instack[t]=0;  
         }  
         while(s!=t);  
     }  
 }  
 int main()  
 {  
     int i,j,a,b,v[10010];  
     cin>>n>>m;  
     f=1;  
     memset(head,-1,sizeof(head));  
     memset(v,0,sizeof(v));  
     for(i=0;i<m;i++)  
     {  
         cin>>a>>b;  
         add(a,b);  
     }  
     memset(DFN,0,sizeof(DFN));  
     for(i=1;i<=n;i++)  
     {  
         if(!DFN[i])  
            tarjan(i);  
     }  
     for(i=1;i<=n;i++)  
         v[Belong[i]]++;  
     long long sum=0;  
     for(i=0;i<=n;i++)  
     {  
         if(v[i]>1)  
        sum=sum+v[i]*(v[i]-1)/2;  
     }  
     cout<<sum<<endl;  
     return 0;  
 }  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值