201509-4 高速公路 tarjan強連通分量演算法 O(V+E)
阿新 • • 發佈:2018-12-15
#include<iostream>
#include<algorithm>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<vector>
#include<string>
#include<limits.h>
#include<cmath>
#include<map>
#include<queue>
#include<set>
#include<stack>
#include<functional>
#define iter(i,start,end) for(int (i)=(start);(i)<(end);(i)++)
using namespace std;
const int nmax=10000+5;
int n,m; //n城市個數\in[1,10000] m單向高速公路個數\in[1,100000]
vector<int>g[nmax];
int groupnum,time,ans; //groupnum強連通分量的數量(從1開始計數 time時間 ans強連通分量中點對的數量
bool onstack[nmax]; //是否在棧內
int group[nmax],low[nmax],dfn[nmax],member[nmax]; //low記錄該點最早能回溯到的地方 dfn各點的時間戳 member[i]記錄第i組有幾個點【其實這個陣列可以通過邊遍歷邊記錄ans省下來】
stack<int> s;
void init();
void tarjan(int cur);
int main()
{
//freopen("201509-4.txt","r",stdin);
while(scanf("%d %d",&n,&m)==2)
{
init();
while (!s.empty()) s.pop();
time=1;
iter(i,0,n){
if(!dfn[i])
tarjan(i);
}
iter(i,0,n)
member[group[i]]++;
sort(member+1,member+groupnum+1,greater<int>()); //【記錄下是不是這麼寫的】
iter(i,1,groupnum+1){
if(member[i]>1)
ans+=member[i]*(member[i]-1)/2;
}
cout<<ans;
}
return 0;
}
void tarjan(int cur){
low[cur]=dfn[cur]=time++;
onstack[cur]=true; s.push(cur); //【記錄】這幾個stl的函式
iter(i,0,g[cur].size()){
int to=g[cur][i];
if(!dfn[to]){ //如果遍歷過就不要進去了 不然dfn和low陣列都會變化的
tarjan(to);
if(low[to]<low[cur]) //或者直接用Min(low[to],low[cur])代替
low[cur]=low[to];
}
else{
if(onstack[to] && dfn[to] < low[cur]) //在這裡wa了半天 忘了判斷dfn[to] < low[cur]了
low[cur]=dfn[to]; //如果直接用Min(low[cur],dfn[to])代替 就不會wa這麼久了...吃了沒讀書的虧
}
}
if(low[cur]==dfn[cur]) //小環套大環也不怕
{
int tmp=-1,cnt=0; //tmp賦為-1是因為節點編號從0開始的
while(tmp!=cur){
tmp=s.top(); s.pop();
group[tmp]=groupnum;
onstack[tmp]=false;
cnt++;
}
groupnum++;
if(cnt>1) ans+=cnt*(cnt-1)/2; //如果強連通分量只由一個數組成,也不存在什麼點對之說了
}
}
void init(){
memset(g,0,sizeof(g));
int u,v;
iter(i,0,m){
cin>>u>>v;
g[u-1].push_back(v-1);
}
groupnum=1,time=0,ans=0;
memset(onstack,0,sizeof(onstack));
memset(group,0,sizeof(group)); //0表示還沒分組
memset(low,0,sizeof(low)); memset(dfn,0,sizeof(dfn));
memset(member, 0, sizeof(cout));
}