标签:size main mem 节点 代码 超级 算法 def eof
简单的不能再简单的差分约束裸题啦。(但是我却深感出题人的恶意)
给出一张有 \(n\) 个点的图,以及 \(m\) 对点的数量关系,问是否可以满足每一对关系。
其中一共有三种数量关系:
差分约束...没什么好讲的了。
建立完图论模型后,其实还有潜在的数量关系:每个点的点权 \(\geq 0\)。
\(a-0\leq 0\),即 \(e(0,a)=0\)。
然后再建立一个超级节点 \(n+1\),建立 \(e(n+1,i)=0(0\leq i\leq n)\)。
如果有负环就输出 No,否则输出 Yes。(用某已死算法 spfa 即可)
但是写完一交发现 TLE 4个点,深感数据的良心,所以决定优化一番。
首先最后那个 \(e(0,a)=0\) 的那个边其实可以不用建立,因为一旦出现负权情况就会直接 No。
所以再删除 一个节点+n条边 之后时间宽裕了一点,加上 O2 就可以跑过了。
至于没有 O2 的情况...,找一个 spfa 的 dfs 优化好了。
主要是建边,然后就是 spfa 裸题了。(记得开 O2)
#include<cstdio>
#include<cstring>
#include<iostream>
#include<cmath>
#include<queue>
#define N 20010
using namespace std;
int n,m,head[N],dis[N],sum[N],cnt=0;
bool vis[N];
struct Edge{
int nxt,to,val;
}ed[N<<1];
int read(){
int x=0,f=1;char c=getchar();
while(c<‘0‘ || c>‘9‘) f=(c==‘-‘)?-1:1,c=getchar();
while(c>=‘0‘ && c<=‘9‘) x=x*10+c-48,c=getchar();
return x*f;
}
void add(int u,int v,int w){
ed[++cnt].nxt=head[u];
ed[cnt].to=v,ed[cnt].val=w;
head[u]=cnt;
return;
}
bool spfa(int s){
queue<int>q;
memset(dis,0x3f,sizeof(dis));
memset(vis,false,sizeof(vis));
memset(sum,0,sizeof(sum));
dis[s]=0,vis[s]=true;
q.push(s);
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=false;
if(++sum[u]>=n) return true;
for(int i=head[u];i;i=ed[i].nxt){
int v=ed[i].to,w=ed[i].val;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
if(!vis[v]) q.push(v),vis[v]=true;
}
}
}
return false;
}
int main(){
n=read(),m=read();
for(int i=1;i<=m;i++){
int type=read(),u=read(),v=read(),w;
if(type==1) w=read(),add(u,v,-w);
else if(type==2) w=read(),add(v,u,w);
else add(u,v,0),add(v,u,0);
}
for(int i=1;i<=n;i++) add(0,i,0);
if(spfa(0)) puts("No");
else puts("Yes");
return 0;
}
完结撒花
标签:size main mem 节点 代码 超级 算法 def eof
原文地址:https://www.cnblogs.com/lpf-666/p/12829041.html