开一个大坑 网络流专题啥的晚点再补把
先把连通图弄懂
Network of Schools POJ - 1236 tarjan缩点模板题
题目思路
题目给了两个问题
给多少个学校就能让其他所有学校都能收到
连接多少个学校能使最后给任意一个学校其他所有学校都能
用tarjan进行缩点 在统计随点后图上每个点的出入度
入度为0的点的数量就是第一个答案
max(入度为0的点的数量,入度为0的点的数量)就是第二个答案
还有就是不要忘记原本就是强连通图的情况
ac代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 2e5+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
struct node
{
int to,next;
}e[maxn];
int n,m,len,first[maxn];
int dfn[maxn],low[maxn],belong[maxn],in[maxn],out[maxn];
int ins[maxn],sz[maxn],st[maxn];
int block,id,tp;
void add(int u,int v)
{
e[len].to=v;
e[len].next=first[u];
first[u]=len++;
}
void init()
{
id=tp=block=0;
len=0;
ms(first,-1);
ms(low,0);
ms(dfn,0);
ms(sz,0);
ms(out,0);
ms(in,0);
}
void tarjan(int u)
{
dfn[u]=low[u]=++id;
ins[u]=1;
st[++tp]=u;
for(int i=first[u];i!=-1;i=e[i].next)
{
int v=e[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(low[u]==dfn[u])
{
block++;
int v;
do{
v=st[tp--];
ins[v]=0;
belong[v]=block;
sz[block]++;
}while(u!=v);
}
}
int main()
{
int n;
while(~scanf("%d",&n))
{
ms(first,-1);init();
for(int i=1;i<=n;i++)
{
int x;
while(scanf("%d",&x))
{
if(x!=0)
add(i,x);
else
break;
}
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int i=1;i<=n;i++)
{
for(int j=first[i];j!=-1;j=e[j].next)
{
int u=i,v=e[j].to;
if(belong[u]!=belong[v])
{
in[belong[v]]++;
out[belong[u]]++;
}
}
}
int ii=0,oo=0;
if(block==1)
{
printf("1\n0\n");
}else
{
for(int i=1;i<=block;i++)
{
if(in[i]==0)
ii++;
if(out[i]==0)
oo++;
}
printf("%d\n%d\n",ii,max(oo,ii));
}
}
}
Network UVA - 315 求割点模板题
题目思路
题目要求的是图的割点
套tarjan求割点的板子就好了
读入有点毒瘤 但慢慢写也还好
ac代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 2e5+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
struct node
{
int to,next;
}e[maxn];
int n,len,first[maxn],dfn[maxn],low[maxn],st[maxn],indexx,ins[maxn];
int cot,vis[maxn];
void add(int u,int v)
{
e[len].to=v;
e[len].next=first[u];
first[u]=len++;
}
void init()
{
len=indexx=0;
cot=0;
ms(first,-1);
ms(dfn,0);
ms(low,0);
ms(ins,0);
ms(vis,0);
}
void tarjan(int u,int fa)
{
int ch=0;
low[u]=dfn[u]=++indexx;
ins[u]=1;
for(int i=first[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(v==fa)continue;
if(!dfn[v])
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>=dfn[u]&&u!=fa)vis[u]=1;//这里似乎不能直接统计 可能会有重复
if(u==fa)ch++;
}else if(ins[v]) low[u]=min(low[u],dfn[v]);
}
if(ch>=2&&u==fa)vis[u]=1;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
init();
int x;
while(~scanf("%d",&x)&&x)
{
int u;
char tem;
while(~scanf("%d%c",&u,&tem))
{
add(x,u),add(u,x);
if(tem=='\n')break;
}
}
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i,i);
for(int i=1;i<=n;i++)
if(vis[i]==1)
cot++;
printf("%d\n",cot);
}
}
Critical Links UVA - 796 求桥模板题
题目思路
这题就是要找桥 套个板子就好
有几个需要注意的地方
1 输入的时候可能会有重边
一开始准备每次建边只见一个方向这样就不会有重边了
但是这样不好输出
所以就改成了 只让起点小的建边
2 输出的时候还要单独换下行 不然会报pe 就挺恶心人的
uva的题目每次交都要等好久甚至还submit failed
头疼得很
ac代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 2e5+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
struct node
{
int to,next,from;
}e[maxn];
struct point
{
int a,b;
}ans[maxn];
int n,len,first[maxn],dfn[maxn],low[maxn],st[maxn],indexx,ins[maxn];
int cot,vis[maxn],bridge[maxn];
void add(int u,int v)
{
e[len].to=v;
e[len].from=u;
e[len].next=first[u];
first[u]=len++;
}
void init()
{
len=indexx=0;
cot=0;
ms(first,-1);
ms(dfn,0);
ms(low,0);
ms(ins,0);
ms(vis,0);
ms(bridge,0);
}
void tarjan(int u,int fa)
{
dfn[u]=low[u]=++indexx;
for(int i=first[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(!dfn[v])
{
tarjan(v,u);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u])
{
//cot++;
bridge[i]=bridge[i^1]=1;
}
}else if(v!=fa)
low[u]=min(low[u],dfn[v]);
}
}
int main()
{
while(~scanf("%d",&n))
{
init();
for(int i=1;i<=n;i++)
{
int x,m;
scanf("%d (%d)",&x,&m);
for(int j=1;j<=m;j++)
{
int v;
scanf("%d",&v);
if(x>v)continue;
add(x,v),add(v,x);
}
}
for(int i=0;i<n;i++)
if(!dfn[i])
tarjan(i,-1);
for(int i=0;i<len;i+=2)
{
if(bridge[i])
{
ans[++cot].a=e[i].from;
ans[cot].b=e[i].to;
}
}
printf("%d critical links\n",cot);
for(int i=1;i<=cot;i++)
printf("%d - %d\n",ans[i].a,ans[i].b);
printf("\n");
}
}
Caocao’s Bridges HDU - 4738 找桥的最小权值
题目思路
这题也是拿tarjan找桥 但是坑点挺多的 看了下面的提示才知道
这题首先要找桥的最小权值
然后如果本身就不是连通图 那么直接输出0
如果桥最小权值是0 也需要带一个人 所以直接输出1
如果没桥输出-1
剩下的情况直接输出
说实话如果没提示的话得wa到明天去
ac代码
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <math.h>
#include <string.h>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <set>
#include <utility>
#define pi 3.1415926535898
#define ll long long
#define lson rt<<1
#define rson rt<<1|1
#define eps 1e-6
#define ms(a,b) memset(a,b,sizeof(a))
#define legal(a,b) a&b
#define print1 printf("111\n")
using namespace std;
const int maxn = 1e6+10;
const int inf = 0x3f3f3f3f;
const ll llinf =0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
struct node
{
int to,next,v;
}e[maxn];
int n,m,ans,len,first[maxn],dfn[maxn],low[maxn],st[maxn],indexx,ins[maxn];
int cot,vis[maxn],bridge[maxn];
void add(int u,int v,int w)
{
e[len].to=v;
//e[len].from=u;
e[len].v=w;
e[len].next=first[u];
first[u]=len++;
}
void init()
{
len=indexx=0;
cot=0;
ans=inf;
ms(first,-1);
ms(dfn,0);
ms(low,0);
ms(ins,0);
ms(vis,0);
ms(bridge,0);
}
void tarjan(int u,int edge)
{
dfn[u]=low[u]=++indexx;
for(int i=first[u];i!=-1;i=e[i].next)
{
int v=e[i].to;
if(!dfn[v])
{
tarjan(v,i);
low[u]=min(low[u],low[v]);
if(low[v]>dfn[u])
{
//cot++;
ans=min(ans,e[i].v);
}
}else if((i^1)!=edge)
low[u]=min(low[u],dfn[v]);
}
}
int main()
{
while(~scanf("%d%d",&n,&m)&&n+m)
{
init();
for(int i=1;i<=m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
int tim=0;
for(int i=1;i<=n;i++)
if(!dfn[i])
{
tarjan(i,-1);
tim++;
}
if(tim>1)
printf("0\n");
else if(ans==inf)
printf("-1\n");
else if(ans==0)
printf("1\n");
else
printf("%d\n",ans);
}
}