4/24 tarjin+差分约束
Posted 钟钟终
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了4/24 tarjin+差分约束相关的知识,希望对你有一定的参考价值。
P1993 小 K 的农场
注意建图的方式,共有三种情况:
1.a-b>=c,
2.a-b<=c
3.a==c
需要统一格式,如果都是">=",就要跑最长路;相反,若是小于等于,就是最短路。
建图时由减数指向被减数,即为b指向a。
#include <bits/stdc++.h>
using namespace std;
const int maxn=2e5+5;
const int inf=0x3f3f3f3f;
int n,m,head[maxn],cnt,dist[maxn],num[maxn];
bool vis[maxn];
struct node
int to,nxt,dis;
e[maxn];
void add(int u,int v,int w)
e[++cnt].to=v;
e[cnt].dis=w;
e[cnt].nxt=head[u];
head[u]=cnt;
queue<int>q;
bool spfa(int u)
memset(dist,inf,sizeof(dist));
dist[u]=0;
q.push(u);
vis[u]=1;
num[u]=1;
while(!q.empty())
int u=q.front();q.pop();
vis[u]=0;
for(int i=head[u];i;i=e[i].nxt)
int v=e[i].to;
if(dist[v]>dist[u]+e[i].dis)
dist[v]=dist[u]+e[i].dis;
num[v]++;
if(num[v]>=n)
return 0;
if(!vis[v])
q.push(v);
vis[v]=1;
return 1;
signed main()
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) //建立超级源点
add(n+1,i,0);
for(int k=1;k<=m;k++)
int g;
scanf("%d",&g);
if(g==1)
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(u,v,-w);
else if(g==2)
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
add(v,u,w);
else
int u,v;
scanf("%d%d",&u,&v);
add(u,v,0);
add(v,u,0);
if(spfa(n+1))
cout<<"Yes"<<endl;
else
cout<<"No"<<endl;
return 0;
找到图中强连通分量的个数,可将每个强连通分量看作一个点,类似缩点的思想:
1.记录他们的长度和入读
2.可记录每个分量中点的个数
#include <bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int n,m,head[maxn],cnt,dfn[maxn],low[maxn],bl[maxn],tim;
int inq[maxn],v[maxn],nxt[maxn],tol,in[maxn],ans,du[maxn];
stack<int>q;
void add(int u,int v1)
v[++cnt]=v1;
nxt[cnt]=head[u];
head[u]=cnt;
void tarjan(int u)
dfn[u]=low[u]=++tim;
q.push(u);
inq[u]=1;
for(int i=head[u];i;i=nxt[i])
int v1=v[i];
if(!dfn[v1])
tarjan(v1);
low[u]=min(low[u],low[v1]);
else if(inq[v1])
low[u]=min(low[u],dfn[v1]);
if(dfn[u]==low[u])
tol++;int tmp;
do
tmp=q.top();
q.pop();
inq[tmp]=0;
in[tol]++; //此强连通分量的点数
bl[tmp]=tol; //缩点操作
while(tmp!=u);
int main()
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
int u,v1;scanf("%d%d",&u,&v1);
add(u,v1);
for(int i=1;i<=n;i++)
if(!dfn[i])
tarjan(i);
for(int f=1;f<=n;f++)
for(int i=head[f];i;i=nxt[i])
int vv=v[i];
if(bl[f]!=bl[vv])
du[bl[f]]++;
int tt=0;
for(int i=1;i<=tol;i++)
if(!du[i])
if(tt)
cout<<0<<endl;
return 0;
tt=i; //只能一个点出度为0
cout<<in[tt]<<endl;
return 0;
以上是关于4/24 tarjin+差分约束的主要内容,如果未能解决你的问题,请参考以下文章