BZOJ1093: [ZJOI2007]最大半连通子图

1093: [ZJOI2007]最大半连通子图

Time Limit: 30 Sec  Memory Limit: 162 MB
Submit: 1530  Solved: 589
[Submit][Status]

Description

Input

第一行包含两个整数N,M,X。N,M分别表示图G的点数与边数,X的意义如上文所述。接下来M行,每行两个正整数a, b,表示一条有向边(a, b)。图中的每个点将编号为1,2,3…N,保证输入中同一个(a,b)不会出现两次。

Output

应包含两行,第一行包含一个整数K。第二行包含整数C Mod X.

Sample Input

6 6 20070603
1 2
2 1
1 3
2 4
5 6
6 4

Sample Output

3
3

HINT

 

对于20%的数据, N ≤18;对于60%的数据, N ≤10000;对于100%的数据, N ≤100000, M ≤1000000;对于100%的数据, X ≤10^8。

 

Source

题解:

按输入构图,tarjan缩点之后变为DAG,最大节点数即为“最长链”,一条链的长度定义为所有节点的权值之和,每个scc的权值为它的节点个数

最长链的求法类似于拓扑排序+DP

求构成方案只要在取max的时候判断一下即可,利用加法原理

答案扫一遍即可(ms也可以加一个虚拟节点,由所有scc向它连边,然后最后直接输出该点的信息就行。。。)

本题还有一个注意的地方就是tarjan之后重构图的时候会加入重边,要消除重边的影响可以在topsort的时候对访问过的节点做一下标记

具体实现见代码

代码:

1.

  1 const maxn=110000+1000;maxm=1100000+1000;
  2 type node=record
  3      from,go,next:longint;
  4      end;
  5 var e:array[0..maxm] of node;
  6     e2:array[0..maxm] of node;
  7     a,b:array[0..maxm] of longint;
  8     n,m,h,t,x,y,i,ti,top,cnt,ans1,ans2,tot,p:longint;
  9     q,head,head2,dfn,low,sta,scc,s,v,num,inp,vis:array[0..maxn] of longint;
 10     function min(x,y:longint):longint;
 11      begin
 12      if x<y then exit(x) else exit(y);
 13      end;
 14 
 15 procedure insert(x,y:longint);
 16  begin
 17  inc(tot);
 18  e[tot].go:=y;e[tot].next:=head[x];head[x]:=tot;
 19  end;
 20 procedure insert2(x,y:longint);
 21  begin
 22  inc(tot);
 23  e2[tot].go:=y;e2[tot].next:=head2[x];head2[x]:=tot;
 24  end;
 25 procedure dfs(x:longint);
 26  var i,y,z:longint;
 27  begin
 28  inc(ti);dfn[x]:=ti;low[x]:=ti;inc(top);sta[top]:=x;
 29  i:=head[x];
 30  while i<>0 do
 31   begin
 32    y:=e[i].go;
 33    if dfn[y]=0 then
 34     begin
 35     dfs(y);
 36     low[x]:=min(low[x],low[y]);
 37     end
 38    else if scc[y]=0 then low[x]:=min(low[x],dfn[y]);
 39   i:=e[i].next;
 40   end;
 41  if low[x]=dfn[x] then
 42   begin
 43   inc(cnt);
 44   while true do
 45    begin
 46    z:=sta[top];dec(top);
 47    scc[z]:=cnt;inc(s[cnt]);
 48    if z=x then break;
 49    end;
 50   end;
 51  end;
 52 procedure tarjan;
 53  begin
 54  ti:=0;cnt:=0;ti:=0;
 55  fillchar(dfn,sizeof(dfn),0);
 56  for i:=1 to n do if dfn[i]=0 then dfs(i);
 57  end;
 58 procedure init;
 59  begin
 60    readln(n,m,p);
 61    for i:=1 to m do
 62     begin
 63      readln(a[i],b[i]);
 64      insert(a[i],b[i]);
 65     end;
 66  end;
 67 procedure main;
 68  begin
 69    tarjan;
 70    fillchar(inp,sizeof(inp),0);tot:=0;
 71    for i:=1 to m do
 72     begin
 73     x:=scc[a[i]];y:=scc[b[i]];
 74     if x<>y then begin inc(inp[y]);insert2(x,y);end;
 75     end;
 76    h:=0;t:=0;
 77    for i:=1 to cnt do
 78     if inp[i]=0 then begin inc(t);q[t]:=i;v[i]:=s[i];num[i]:=1;end;
 79    while h<t do
 80     begin
 81     inc(h);x:=q[h];
 82     i:=head2[x];
 83     while i<>0 do
 84      begin
 85      y:=e2[i].go;
 86      if vis[y]<>x then
 87       begin
 88       vis[y]:=x;
 89       if v[x]+s[y]>v[y] then begin v[y]:=v[x]+s[y];num[y]:=num[x];end
 90       else if v[x]+s[y]=v[y] then num[y]:=(num[y]+num[x]) mod p;
 91       end;
 92      dec(inp[y]);if inp[y]=0 then begin inc(t);q[t]:=y;end;
 93      i:=e2[i].next;
 94      end;
 95     end;
 96    ans1:=0;ans2:=0;
 97    for i:=1 to cnt do if v[i]>ans1 then begin ans1:=v[i];ans2:=num[i];end
 98    else if v[i]=ans1 then ans2:=(ans2+num[i]) mod p;
 99    writeln(ans1);
100    writeln(ans2);
101  end;
102 begin
103   assign(input,'input.txt');assign(output,'output.txt');
104   reset(input);rewrite(output);
105   init;
106   main;
107   close(input);close(output);
108 end.   
View Code

2.加虚拟节点

  1 const maxn=110000+1000;maxm=1100000+1000;
  2 type node=record
  3      from,go,next:longint;
  4      end;
  5 var e:array[0..maxm] of node;
  6     e2:array[0..2*maxm] of node;
  7     a,b:array[0..maxm] of longint;
  8     n,m,h,t,x,y,i,ti,top,cnt,ans1,ans2,tot,p:longint;
  9     q,head,head2,dfn,low,sta,scc,s,v,num,inp,vis:array[0..maxn] of longint;
 10     function min(x,y:longint):longint;
 11      begin
 12      if x<y then exit(x) else exit(y);
 13      end;
 14 
 15 procedure insert(x,y:longint);
 16  begin
 17  inc(tot);
 18  e[tot].go:=y;e[tot].next:=head[x];head[x]:=tot;
 19  end;
 20 procedure insert2(x,y:longint);
 21  begin
 22  inc(tot);
 23  e2[tot].go:=y;e2[tot].next:=head2[x];head2[x]:=tot;
 24  end;
 25 procedure dfs(x:longint);
 26  var i,y,z:longint;
 27  begin
 28  inc(ti);dfn[x]:=ti;low[x]:=ti;inc(top);sta[top]:=x;
 29  i:=head[x];
 30  while i<>0 do
 31   begin
 32    y:=e[i].go;
 33    if dfn[y]=0 then
 34     begin
 35     dfs(y);
 36     low[x]:=min(low[x],low[y]);
 37     end
 38    else if scc[y]=0 then low[x]:=min(low[x],dfn[y]);
 39   i:=e[i].next;
 40   end;
 41  if low[x]=dfn[x] then
 42   begin
 43   inc(cnt);
 44   while true do
 45    begin
 46    z:=sta[top];dec(top);
 47    scc[z]:=cnt;inc(s[cnt]);
 48    if z=x then break;
 49    end;
 50   end;
 51  end;
 52 procedure tarjan;
 53  begin
 54  ti:=0;cnt:=0;ti:=0;
 55  fillchar(dfn,sizeof(dfn),0);
 56  for i:=1 to n do if dfn[i]=0 then dfs(i);
 57  end;
 58 procedure init;
 59  begin
 60    readln(n,m,p);
 61    for i:=1 to m do
 62     begin
 63      readln(a[i],b[i]);
 64      insert(a[i],b[i]);
 65     end;
 66  end;
 67 procedure main;
 68  begin
 69    tarjan;
 70    fillchar(inp,sizeof(inp),0);tot:=0;
 71    for i:=1 to m do
 72     begin
 73     x:=scc[a[i]];y:=scc[b[i]];
 74     if x<>y then begin inc(inp[y]);insert2(x,y);end;
 75     end;
 76    for i:=1 to cnt do insert2(i,cnt+1);
 77    inp[cnt+1]:=cnt;s[cnt+1]:=0;
 78    h:=0;t:=0;
 79    for i:=1 to cnt do
 80     if inp[i]=0 then begin inc(t);q[t]:=i;v[i]:=s[i];num[i]:=1;end;
 81    while h<t do
 82     begin
 83     inc(h);x:=q[h];
 84     i:=head2[x];
 85     while i<>0 do
 86      begin
 87      y:=e2[i].go;
 88      if vis[y]<>x then
 89       begin
 90       vis[y]:=x;
 91       if v[x]+s[y]>v[y] then begin v[y]:=v[x]+s[y];num[y]:=num[x];end
 92       else if v[x]+s[y]=v[y] then num[y]:=(num[y]+num[x]) mod p;
 93       end;
 94      dec(inp[y]);if inp[y]=0 then begin inc(t);q[t]:=y;end;
 95      i:=e2[i].next;
 96      end;
 97     end;
 98    writeln(v[cnt+1]);
 99    writeln(num[cnt+1]);
100  end;
101 begin
102   assign(input,'input.txt');assign(output,'output.txt');
103   reset(input);rewrite(output);
104   init;
105   main;
106   close(input);close(output);
107 end.                         
View Code

 

posted @ 2014-08-11 14:32  ZYF-ZYF  Views(257)  Comments(0Edit  收藏  举报