您的位置:首页 > 其它

UVA 11324强连通分量缩点+DAG上最长路(不明白算法为什么正确ing)

2014-03-01 00:10 288 查看
/*UVA 11324强连通分量缩点+DAG上最长路(不明白算法为什么正确ing)
主要是为了练习缩点和GAD
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <string>
#include <iostream>
#include <sstream>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <list>
#include <set>
#include <algorithm>
#define INF 0x3f3f3f3f
#define LL long long
#define eps 1e-7
#define maxn 1100
using namespace std;

//scc_cnt是计数器
//sccno[i]是i属于的分量
//注意scc不像bcc,分量间是没有公共点的

int t,n,m;

int pre[maxn] ,sccno[maxn] , low[maxn], dfs_clock , scc_cnt;
stack<int>S;
vector<int>G[maxn] ,scc[maxn];
void dfs(int u){
low[u] = pre[u] = ++dfs_clock;
S.push(u);
int ecnt = G[u].size();
for(int i=0;i<ecnt ; i++){
int v = G[u][i];
if(!pre[v]){
dfs(v);
low[u] = min(low[u] , low[v]);
}
else if(!sccno[v]){
low[u] = min(low[u] , pre[v]);
}
}
if(low[u] == pre[u]){
scc[++scc_cnt].clear();
while(true){
int x = S.top(); S.pop();
sccno[x] = scc_cnt;
scc[scc_cnt].push_back(x);
if(x == u) break;
}
}
}
void find_scc(int n){
memset(pre ,0 ,sizeof(pre));
memset(sccno ,0 ,sizeof(sccno));
dfs_clock = scc_cnt = 0;
for(int i=1;i<=n;i++){
if(!pre[i]) dfs(i);
}
}

bool G1[maxn][maxn];//新图的邻接矩阵,方便判断
void BuiltNG()//建立缩点后的新的DAG图
{
memset(G1,0,sizeof(G1));
for(int i=1;i<=n;i++)//枚举原先的每条边
{
for(int j=0;j<G[i].size();j++)
{
int u=sccno[i],v=sccno[G[i][j]];
if (u!=v) G1[u][v]=true;
}
}
return ;
}
int d[maxn];
int dp(int u)//记忆化搜索求GAD上的最长路,很长时间没写了,需要复习啊
{
int &ans = d[u];
if (ans!=-1) return ans;
ans=0;
for(int i=1;i<=scc_cnt;i++)
{
if (G1[u][i]) ans=max(ans,dp(i));
}
ans+=scc[u].size();
return ans;
}
int solve()
{
int mx=0;
memset(d,-1,sizeof(d));
for(int i=1;i<=scc_cnt;i++)
{
mx=max(mx,dp(i));
}
return mx;
}
int main()
{
cin>>t;
while(t--)
{
cin>>n>>m;
for(int i=1;i<=n;i++) G[i].clear();
for(int i=1;i<=m;i++)
{
int u,v;
cin>>u>>v;
G[u].push_back(v);
}
find_scc(n);
BuiltNG();
cout<<solve()<<endl;

}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: