您的位置:首页 > 产品设计 > UI/UE

UVa 11234 The Largest Clique

2016-08-07 16:42 246 查看

找最长的连接的点的数量。用tarjan缩点,思考可知每一个强连通分量里的点要么都选,要么都不选(走别的路),可以动规解决。

 

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
const int mxn=12000;
int top,stack[mxn];
bool inst[mxn];
int cnt,dnow;
int dfn[mxn],low[mxn];
int belone[mxn];
int ptcnt[mxn];
int dp[mxn];
vector<int> e[mxn];//邻接表
vector<int> pt[mxn];//缩点后的点集
void clear(){
cnt=0;dnow=0;top=0;
memset(dfn,-1,sizeof(dfn));
memset(inst,false,sizeof(inst));
memset(dp,0,sizeof dp);
memset(ptcnt,0,sizeof ptcnt);
memset(belone,0,sizeof belone);
for(int i=1;i<mxn;i++) e[i].clear();
for(int i=1;i<mxn;i++) pt[i].clear();
}
int n,m;
void tarjan(int s){
int v=0,i;
dfn[s]=++dnow;
low[s]=dfn[s];
inst[s]=true;
stack[++top]=s;
int si=e[s].size();
for(i=0;i<si;i++){
v=e[s][i];
if(dfn[v]==-1){
tarjan(v);
low[s]=min(low[v],low[s]);
}
else if(inst[v]){
low[s]=min(dfn[v],low[s]);
}
}
if(dfn[s]==low[s]){
cnt++;
do{
v=stack[top--];
belone[v]=cnt;
inst[v]=false;
}while(s!=v);
}
return;
}
int find(int x){//动规
if(pt[x].size()==0)return dp[x]=ptcnt[x];
if(dp[x])return dp[x];
int mx=0;
for(int i=0;i<pt[x].size();i++){
mx=max(mx,find(pt[x][i]));
}
dp[x]=mx+ptcnt[x];
return dp[x];
}
void solve(){//统计缩完点之后的连通情况
int i,j,k;
for(i=1;i<=n;i++){
ptcnt[belone[i]]++;
for(j=0;j<e[i].size();j++){
int v=e[i][j];
if(belone[i]!=belone[v])
pt[belone[i]].push_back(belone[v]);
}
}
int ans=0;
for(i=1;i<=cnt;i++)ans=max(ans,find(i));
printf("%d\n",ans);
return;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
clear();
int i,j;
int u,v;
for(i=1;i<=m;i++){
scanf("%d%d",&u,&v);
e[u].push_back(v);
}
for(i=1;i<=n;i++){//缩点
if(dfn[i]==-1)tarjan(i);
}
solve();
}
return 0;
}

 

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