TOJ 3365 ZOJ 3232 It's not Floyd Algorithm/強連通成分
3388 ワード
It's not Floyd Algorithm
時間制限(通常/Java):1000 MS/3000 MS実行メモリ制限:65536 KByte
説明
When a directed graph is given, we can solve its transitive closure easily using the well-known Floyd algorithm.
But if you're given a transitive closure, can you give a corresponding directed graph with minimal edges?
入力
About 100 test cases, seperated by blank line.
First line of each case is an integer N (1<=N<=200). The followingN lines represent the given transitive closure in 0-1 matrix form, each line hasN numbers.
しゅつりょく
For each case, just output the number of minimal edges of a directed graph which has a given transitive closure.
サンプル入力
サンプル出力
ヒント
Transitive closure can be presented as a matrix T, where Ti,j is true if and only if there is a path from vertexi toj.
まず、縮点は、各強連通成分に対してn個の点があれば、少なくともn個のエッジだけで連通できる(n=1を除く)
それから縮み点の後の図に対してどのように1回の反閉包をして余分な辺を取り除いて統計してみます
時間制限(通常/Java):1000 MS/3000 MS実行メモリ制限:65536 KByte
説明
When a directed graph is given, we can solve its transitive closure easily using the well-known Floyd algorithm.
But if you're given a transitive closure, can you give a corresponding directed graph with minimal edges?
入力
About 100 test cases, seperated by blank line.
First line of each case is an integer N (1<=N<=200). The followingN lines represent the given transitive closure in 0-1 matrix form, each line hasN numbers.
しゅつりょく
For each case, just output the number of minimal edges of a directed graph which has a given transitive closure.
サンプル入力
1
1
2
1 0
0 1
2
1 1
1 1
3
1 1 1
0 1 1
0 0 1
サンプル出力
0
0
2
2
ヒント
Transitive closure can be presented as a matrix T, where Ti,j is true if and only if there is a path from vertexi toj.
まず、縮点は、各強連通成分に対してn個の点があれば、少なくともn個のエッジだけで連通できる(n=1を除く)
それから縮み点の後の図に対してどのように1回の反閉包をして余分な辺を取り除いて統計してみます
#include<stdio.h>
#include<string.h>
int n;
int dfn[210];
int low[210];
bool instack[210];
int stack[210];
int cnt,num,top;
int a[210][210];
int count[210];
int belong[210];
int map[210][210];
void floyd()
{
int i,j,k;
for(k = 1;k <= cnt; k++)
for(i = 1;i <= cnt; i++)
for(j = 1;j <= cnt; j++)
if(map[i][k] && map[k][j] && map[i][j])
map[i][j] = 0;
}
void tarjan(int i)
{
int j,k;
dfn[i] = low[i] = ++num;
instack[i] = true;
stack[++top] = i;
for(j = 1;j <= n; j++)
{
k = a[i][j];
if(!k)
continue;
if(!dfn[j])
{
tarjan(j);
if(low[i] > low[j])
low[i] = low[j];
}
else if(instack[j] && low[i] > dfn[j])
low[i] = dfn[j];
}
if(low[i] == dfn[i])
{
cnt++;
do
{
j = stack[top--];
instack[j] = false;
belong[j] = cnt;
count[cnt]++;
}
while(i != j);
}
}
int main()
{
int i,j,sum;
while(scanf("%d",&n)!=EOF)
{
for(i = 1;i <= n; i++)
for(j = 1; j<= n; j++)
scanf("%d",&a[i][j]);
num = top = cnt = 0;
memset(dfn,0,sizeof(dfn));
memset(instack,false,sizeof(instack));
memset(count,0,sizeof(count));
memset(map,0,sizeof(map));
for(i = 1;i <= n; i++)
if(!dfn[i])
tarjan(i);
for(i = 1; i<= n; i++)
for(j = 1; j<= n; j++)
if(a[i][j])
if(belong[i] != belong[j])
map[belong[i]][belong[j]] = 1;
sum = 0;
floyd();
for(i = 1;i <= cnt; i++)
if(count[i] != 1)
sum += count[i];
for(i = 1;i <= cnt; i++)
for(j = 1; j<= cnt; j++)
if(map[i][j])
sum++;
printf("%d
",sum);
}
return 0;
}