UVA 12167 加最少的边让其变为连通图
2014-05-13 20:34
253 查看
ejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&category=&problem=3319&mosmsg=Submission+received+with+ID+13628687
Consider the following exercise, found in a generic linear algebra textbook.
Let A be an n × n matrix. Prove that the following statements are equivalent:
A is invertible.
Ax = b has exactly one solution for every n × 1 matrix b.
Ax = b is consistent for every n × 1 matrix b.
Ax = 0 has only the trivial solution x = 0.
The typical way to solve such an exercise is to show a series of implications. For instance, one can proceed by showing that (a) implies (b), that (b) implies (c), that (c) implies (d), and finally that (d) implies
(a). These four implications show that the four statements are equivalent.
Another way would be to show that (a) is equivalent to (b) (by proving that (a) implies (b) and that (b) implies (a)), that (b) is equivalent to (c), and that (c) is equivalent to (d). However, this way requires
proving six implications, which is clearly a lot more work than just proving four implications!
I have been given some similar tasks, and have already started proving some implications. Now I wonder, how many more implications do I have to prove? Can you help me determine this?
One line containing two integers n (1 ≤ n ≤ 20000) and m (0 ≤ m ≤ 50000): the number of statements and the number of implications that have already been proved.
m lines with two integers s1 and s2 (1 ≤ s1, s2 ≤ n and s1 ≠ s2) each, indicating that it has been proved that statement s1 implies
statement s2.
One line with the minimum number of additional implications that need to be proved in order to prove that all statements are equivalent.
The 2008 ACM Northwestern European Programming Contest
图的连通性。在一个有向图上增加一些边,使其变为强连通图。先求强连通分量,将所有强连通分量缩为一个点,然后统计缩点后的图中入度为零和出度为零的点的个数,去最大即为所求。
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
const int N=100005;
int head
,ip,in
,out
,stack
,ins
,index,dfn
,low
,ee
[2],belong
;
int cnt_tar,top,m,n;
struct note
{
int to;
int next;
}edge
;
void add(int u,int v)
{
edge[ip].to=v;
edge[ip].next=head[u];
head[u]=ip++;
}
void tarjan(int u)
{
int j,i,v;
dfn[u]=low[u]=++index;
stack[++top]=u;
ins[u]=1;
for(i=head[u]; i!=-1; i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(ins[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
cnt_tar++;
do
{
j=stack[top--];
ins[j]=0;
belong[j]=cnt_tar;
}
while(j!=u);
}
}
void solve()
{
int i;
top=0,index=0,cnt_tar=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
for(i=1; i<=n; i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(head,-1,sizeof(head));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
scanf("%d%d",&ee[i][0],&ee[i][1]);
add(ee[i][0],ee[i][1]);
}
solve();
for(int i=1; i<=m; i++)
{
int xx=belong[ee[i][0]],yy=belong[ee[i][1]];
if(xx!=yy)
{
in[yy]++;
out[xx]++;
}
}
int innum=0,outnum=0;
for(int i=1; i<=cnt_tar; i++)
{
if(in[i]==0)
innum++;
if(out[i]==0)
outnum++;
}
printf("%d\n",max(innum,outnum));
}
return 0;
}
Consider the following exercise, found in a generic linear algebra textbook.
Let A be an n × n matrix. Prove that the following statements are equivalent:
A is invertible.
Ax = b has exactly one solution for every n × 1 matrix b.
Ax = b is consistent for every n × 1 matrix b.
Ax = 0 has only the trivial solution x = 0.
The typical way to solve such an exercise is to show a series of implications. For instance, one can proceed by showing that (a) implies (b), that (b) implies (c), that (c) implies (d), and finally that (d) implies
(a). These four implications show that the four statements are equivalent.
Another way would be to show that (a) is equivalent to (b) (by proving that (a) implies (b) and that (b) implies (a)), that (b) is equivalent to (c), and that (c) is equivalent to (d). However, this way requires
proving six implications, which is clearly a lot more work than just proving four implications!
I have been given some similar tasks, and have already started proving some implications. Now I wonder, how many more implications do I have to prove? Can you help me determine this?
Input
On the first line one positive number: the number of testcases, at most 100. After that per testcase:One line containing two integers n (1 ≤ n ≤ 20000) and m (0 ≤ m ≤ 50000): the number of statements and the number of implications that have already been proved.
m lines with two integers s1 and s2 (1 ≤ s1, s2 ≤ n and s1 ≠ s2) each, indicating that it has been proved that statement s1 implies
statement s2.
Output
Per testcase:One line with the minimum number of additional implications that need to be proved in order to prove that all statements are equivalent.
Sample Input
2 4 0 3 2 1 2 1 3
Sample Output
4 2
The 2008 ACM Northwestern European Programming Contest
图的连通性。在一个有向图上增加一些边,使其变为强连通图。先求强连通分量,将所有强连通分量缩为一个点,然后统计缩点后的图中入度为零和出度为零的点的个数,去最大即为所求。
#include <stdio.h>
#include <string.h>
#include <iostream>
using namespace std;
const int N=100005;
int head
,ip,in
,out
,stack
,ins
,index,dfn
,low
,ee
[2],belong
;
int cnt_tar,top,m,n;
struct note
{
int to;
int next;
}edge
;
void add(int u,int v)
{
edge[ip].to=v;
edge[ip].next=head[u];
head[u]=ip++;
}
void tarjan(int u)
{
int j,i,v;
dfn[u]=low[u]=++index;
stack[++top]=u;
ins[u]=1;
for(i=head[u]; i!=-1; i=edge[i].next)
{
v=edge[i].to;
if(!dfn[v])
{
tarjan(v);
low[u]=min(low[u],low[v]);
}
else if(ins[v])
low[u]=min(low[u],dfn[v]);
}
if(dfn[u]==low[u])
{
cnt_tar++;
do
{
j=stack[top--];
ins[j]=0;
belong[j]=cnt_tar;
}
while(j!=u);
}
}
void solve()
{
int i;
top=0,index=0,cnt_tar=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
for(i=1; i<=n; i++)
{
if(!dfn[i])
{
tarjan(i);
}
}
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(head,-1,sizeof(head));
memset(in,0,sizeof(in));
memset(out,0,sizeof(out));
scanf("%d%d",&n,&m);
for(int i=1; i<=m; i++)
{
scanf("%d%d",&ee[i][0],&ee[i][1]);
add(ee[i][0],ee[i][1]);
}
solve();
for(int i=1; i<=m; i++)
{
int xx=belong[ee[i][0]],yy=belong[ee[i][1]];
if(xx!=yy)
{
in[yy]++;
out[xx]++;
}
}
int innum=0,outnum=0;
for(int i=1; i<=cnt_tar; i++)
{
if(in[i]==0)
innum++;
if(out[i]==0)
outnum++;
}
printf("%d\n",max(innum,outnum));
}
return 0;
}
相关文章推荐
- uva 12167 - Proving Equivalences(强连通缩点,4级)
- uva 12167 - Proving Equivalences(强连通缩点,4级)
- 加最少边使得DAG图变为一个强连通图
- UVA 11384 最少操作使数列变为零 (找规律)
- HDU2767 有向图加最少边变强连通
- 最少交换次数 UVA 10573 Meeting with Aliens
- 强连通 UVA 1327 King's Quest
- UVA 1660 Cable TV Network——最小割求点连通度
- uva10148相交区间插入m个点,求插入最少的点
- HDU 2767--Proving Equivalences【scc缩点构图 && 求向图中最少增加多少条边才可以使新图强连通】
- 考试题目讲解-【第3题】最少连通代价
- [Uva247][Tarjan求强连通分量][Calling Circles]
- hdoj 1827 Summer Holiday 【有向图 连通最少的点来间接连通所有点】 【tarjan求 SCC + 缩点】
- UVA 11324 The Largest Clique (强连通分量缩点,图DP)
- 【hdu 5945 】 【dp+单调队列优化】Fxx and game【求数x最少经过多少次变换能变为1,(1)如果x%k==0,那么可以x=x/k。(2)x=x-i,(1<=i<=t)】
- uva 11584 题目大意: 给一个字符串, 要求把它分割成若干个子串,使得每个子串都是回文串。问最少可以分割成多少个。
- POJ2375 Cow Ski Area (添最少边构造强连通分量的某个与入度出度相关的结论)
- 增加最少的边使有向图变为强连通图
- UVA 10972 RevolC FaeLoN(边连通分量)
- uva 11584 把字符串分成最少的回文段