一.传递闭包:
传递闭包就是求有向图中两点的可达性。
若从x可以到y,则ok[x][y]=1,否则ok[i][j]=0,然后利用近似Floyd的方法求解
核心代码:
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ok[i][j]|=(ok[i][k]&ok[k][j]);
if(ok[x][y]==1)
printf("YES");
应用:这道题
代码:
#include <iostream>//poj不能用万能头文件
#include <cstdio>
#include <cstring>
using namespace std;
const int maxn=100+10;
int ok[maxn][maxn],a[maxn],ans,n,m,x,y;
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++){
scanf("%d%d",&x,&y);
ok[x][y]=1;//可分出胜负
}
for(int k=1;k<=n;k++)
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
ok[i][j]|=(ok[i][k]&ok[k][j]);//判断能否联通
for(int i=1;i<=n;i++)
for(int j=1;j<=n;j++)
if(i!=j&&(ok[i][j]||ok[j][i]))//如果它们之间有联通
a[i]++;
for(int i=1;i<=n;i++)
if(a[i]==n-1)//如果满足题意
ans++;//答案加1
printf("%d",ans);
return 0;
}
二.最小环
定义:针对有向图而言,从一个点出发,经过一条简单路径回到起点成为环,且在图中长度最小。
解决最小环问题:
核心代码:
g[i][j]=i,j之间的边长
dist=g;
for(int k=1;k<=n;k++)
for(int i=1;i<k;i++)
for(int j=1;j<k;j++)
ans=min(ans,dist[i][j]+g[i][k]+g[k][j]);
三.差分约束
最短路的边就是一个约束!
直接将约束转换为一条边,直接求最短路即可(注意:可能出现负权值,不能用dijkstra,要用SPFA)
Ax-Ay<=t->有向边<y,x>,权值为t
Ax-Ay>=t->有向边<x,y>,权值为-t
若两个不等式为:Ax-Ay>=t,Ax-Ay<=t,则Ax-Ay=t
应用:这道题