题解 P1993 【小K的农场】
ouuan
2018-09-05 13:44:39
竟然全是dfs_SPFA(当然还有一个scc的...),~~你们不知道dfs_SPFA已经死了吗~~
还是slfNB!
差分约束其它题解已经讲的很清楚了,slf就是在spfa入队时如果待入队元素的dis比队首小就从队首入队,否则从队尾入队,可以用deque实现。
至于连通性问题,全部从0连一条零权边确实很简洁,但实测跑的慢一些..我是直接用vis存每个节点是否跑过spfa,没跑过的就跑一遍。
```
#include <iostream>
#include <cstdio>
#include <deque>
#include <cstring>
using namespace std;
void add(int u,int v,int w);
int head[10010],nxt[20010],to[20010],edge[20010],cnt;
int n,m,dis[10010],tot[10010];
bool inq[10010],vis[10010];
deque<int> q;
int main()
{
int i,j,type,c,u,v;
cin>>n>>m;
for (i=1;i<=n;++i)
{
dis[i]=100000000;
}
for (i=0;i<m;++i)
{
cin>>type>>u>>v;
if (type==1)
{
cin>>c;
add(u,v,-c);
}
else if (type==2)
{
cin>>c;
add(v,u,c);
}
else
{
add(u,v,0);
add(v,u,0);
}
}
for (j=1;j<=n;++j)
{
if (!vis[j])
{
memset(tot,0,sizeof(tot));
dis[j]=0;
tot[j]=1;
q.push_front(j);
while (!q.empty())
{
u=q.front();
q.pop_front();
inq[u]=false;
vis[u]=true;
for (i=head[u];i;i=nxt[i])
{
v=to[i];
c=edge[i];
if (dis[v]>dis[u]+c)
{
dis[v]=dis[u]+c;
if (!inq[v])
{
if (++tot[v]>n)
{
cout<<"No";
return 0;
}
inq[v]=true;
if (q.empty()||dis[v]<dis[q.front()]) //slf优化
{
q.push_front(v);
}
else
{
q.push_back(v);
}
}
}
}
}
}
}
cout<<"Yes";
return 0;
}
void add(int u,int v,int w)
{
nxt[++cnt]=head[u];
head[u]=cnt;
to[cnt]=v;
edge[cnt]=w;
}
```