P2812 校園網路【[USACO]Network of Schools加強版】
阿新 • • 發佈:2021-02-19
文章目錄
R e s u l t Result Result
H y p e r l i n k Hyperlink Hyperlink
https://www.luogu.com.cn/problem/P2812
D
e
s
c
r
i
p
t
i
o
n
Description
Description
有 n n n個學校, m m m條單項線路,一條線路 ( x , y ) (x,y) (x,y)連線了 x , y x,y x,y,使得 x x x能共享軟體給 y y y
問最少選幾個學校,使得所有學校都能共享軟體
最少新增幾條線路,可以使得任意學校都能為其他學校共享軟體
資料範圍: n ≤ 1 0 4 , m ≤ 5 × 1 0 6 n\leq 10^4,m\leq 5\times 10^6 n≤104,m≤5×106
S o l u t i o n Solution Solution
首先一個強聯通分量內的學校隨便選一個,整個連通分量就都共享了,所以我們先縮點
第一問顯然就是縮點之後入讀為0的點的個數
第二問則是入度為0的點和出度為0的點的最大值(兩兩匹配)
時間複雜度: O ( n + m ) O(n+m) O(n+m)
C o d e Code Code
#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
#define LL long long
#define N 10010
#define M 5000010
using namespace std;int n,l[N],tot,m;
struct node{int next, to;}e[M];
inline void add(int u,int v){e[++tot]=(node){l[u],v};l[u]=tot;return;}
inline LL read()
{
char c;LL d=1,f=0;
while(c=getchar(),!isdigit(c)) if(c=='-') d=-1;f=(f<<3)+(f<<1)+c-48;
while(c=getchar(),isdigit(c)) f=(f<<3)+(f<<1)+c-48;
return d*f;
}
int x,dfn[N],low[N],stk[N],top,cnt,which[N],siz[N],rd[N],cd[N];
bool vis[N];
inline void Tarjan(int x)
{
dfn[x]=low[x]=++cnt;vis[x]=true;stk[++top]=x;
for(register int i=l[x];i;i=e[i].next)
{
int y=e[i].to;
if(dfn[y]==0)
{
Tarjan(y);
low[x]=min(low[x],low[y]);
}
else if(vis[y]) low[x]=min(low[x],dfn[y]);
}
if(dfn[x]==low[x])
{
int y;
while(y=stk[top--])
{
siz[x]++;
which[y]=x;vis[y]=false;
if(y==x) break;
}
}
}
signed main()
{
n=read();
for(register int i=1;i<=n;i++)
{
while(x=read(),x) add(i,x);
}
for(register int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i);
for(register int i=1;i<=n;i++) for(register int j=l[i];j;j=e[j].next) if(which[i]!=which[e[j].to]) rd[which[e[j].to]]++,cd[which[i]]++;
int tot=0,ans=0,gs=0;
for(register int i=1;i<=n;i++) if(which[i]==i) tot+=rd[i]==0,ans+=cd[i]==0,gs++;
if(gs>1) printf("%d\n%d",tot,max(ans,tot));else puts("1\n0");
}