题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2330
结题报告:
裸的差分约束,本应建负边求最短路,但为了好处理建反图正边,再从0点向每个点建一条长度为1的边确保每个人都至少拿一个糖,最后求最长路即可。
注意数据要卡建边方式,如果Te了可以参考我的建边方式。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<queue>
using namespace std;
int getint()
{
int i=0,f=1;char c;
for(c=getchar();(c<'0'||c>'9')&&c!='-';c=getchar());
if(c=='-')f=-1,c=getchar();
for(;c>='0'&&c<='9';c=getchar())i=(i<<3)+(i<<1)+c-'0';
return i*f;
}
const int N=1e5+5,M=2e5+5;
int n,m,tot,visit[N],exist[N];
long long ans,dis[N];
vector< pair<int,int> > edge[N];
queue<int>q;
void add(int x,int y,int z)
{
edge[x].push_back(make_pair(y,z));
}
int main()
{
//freopen("lx.in","r",stdin);
int op,x,y;
n=getint(),m=getint();
while(m--)
{
op=getint(),x=getint(),y=getint();
if(x==y&&op%2==0)
{
cout<<-1;
return 0;
}
if(op==1)
{
add(y,x,0),add(x,y,0);
continue;
}
if(op==2)
{
add(x,y,1);
continue;
}
if(op==3)
{
add(y,x,0);
continue;
}
if(op==4)
{
add(y,x,1);
continue;
}
if(op==5)
{
add(x,y,0);
continue;
}
}
for(int i=1;i<=n;i++)add(0,i,1);
q.push(0),exist[0]=1,visit[0]=1;
while(!q.empty())
{
int u=q.front();
q.pop();exist[u]=0;
for(int e=0;e<edge[u].size();e++)
{
int v=edge[u][e].first;
if((long long)dis[u]+edge[u][e].second>dis[v])
{
dis[v]=(long long)dis[u]+edge[u][e].second;
if(!exist[v])
{
q.push(v);
exist[v]=1;
visit[v]++;
if(visit[v]==n)
{
cout<<-1;
return 0;
}
}
}
}
}
for(int i=1;i<=n;i++)
ans+=(long long)dis[i];
cout<<ans;
return 0;
}