poi2012 festival
stupid_lulu
posted @ 2013年3月24日 22:39
in poi
, 1356 阅读
强连通分量+最长路
#include<cstdio>
#include<cstring>
const int maxi=100000000;
int ft[610][610];
bool f[100001],can[100001];
int head[100001],next[200001],d[100001];
int dfn[100001],low[100001],sta[100001],g[100001];
int top=0,s=0,sum=0,ss=0,n,m1,m2,ans=0;
struct re{
int u,v,w;
} a[200001];
inline int min(int a,int b){return a<b? a:b;}
inline int max(int a,int b){return a>b? a:b;}
inline int abs(int x){return x>=0? x:-x;}
void done(int i){
++s;
while (sta[top]!=i){
g[sta[top]]=s;
can[sta[top]]=false;
top--;
}
g[i]=s;
can[i]=false;
top--;
}
void dfs(int i){
dfn[i]=low[i]=++ss;
sta[++top]=i;
f[i]=false;
for (int j=head[i];j;j=next[j]){
int k=a[j].v;
if (can[k]){
if (f[k]) dfs(k);
low[i]=min(low[i],min(low[k],dfn[k]));
}
}
if (low[i]==dfn[i]) done(i);
}
void build(int u,int v,int w){
a[++sum].u=u;
a[sum].v=v;
a[sum].w=w;
next[sum]=head[u];
head[u]=sum;
}
int main(){
//freopen("fes11a.in","r",stdin);
scanf("%d%d%d",&n,&m1,&m2);
int u,v;
for (int i=1;i<=m1;i++){
scanf("%d%d",&u,&v);
build(v,u,1);
build(u,v,-1);
}
for (int i=1;i<=m2;i++){
scanf("%d%d",&u,&v);
build(v,u,0);
}
memset(f,true,sizeof(f));
memset(can,true,sizeof(can));
for (int i=1;i<=n;i++){
if (f[i])dfs(i);
}
//for (int i=1;i<=n;i++) printf("g[%d]=%d\n",i,g[i]);
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
ft[i][j]=-maxi;
}
}
//printf("%d\n",ft[1][1]);
for (int i=1;i<=n;i++) ft[i][i]=0;
for (int i=1;i<=sum;i++){
if (g[a[i].u]==g[a[i].v]){
ft[a[i].u][a[i].v]=max(ft[a[i].u][a[i].v],a[i].w);
}
}
/*for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
printf("f[%d][%d]=%d ",i,j,ft[i][j]);
}
printf("\n");
}*/
for (int k=1;k<=n;k++){
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
//if (i==j) printf("i=%d j=%d k=%d f2=%d f3=%d\n",i,j,k,ft[i][k],ft[k][j]);
ft[i][j]=max(ft[i][j],ft[i][k]+ft[k][j]);
}
}
}
/*for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
printf("f[%d][%d]=%d ",i,j,ft[i][j]);
}
printf("\n");
}*/
for (int i=1;i<=n;i++){
if (ft[i][i]>0){
printf("NIE\n");
return 0;
}
}
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
if (g[i]==g[j]) d[g[i]]=max(d[g[i]],abs(ft[i][j]));
}
}
for (int i=1;i<=s;i++){
ans+=d[i]+1;
}
printf("%d\n",ans);
}
评论 (0)