(1)思路:
因为询问最少有多少个糖果,所以可以将老师设为一个源点,想同学们分发糖果,
因为“至少”,所以建图,求最长路之和,
要保证所有小朋友都分到糖果,所以一开始老师最少给学生1个糖果。
如果图中存在环这整情况就不成立。
(2)注意:
一、x = 2,x = 4的中出现x == y 时,会出现环,所以直接就不成立。
二、用数组模拟队列会更快,这里不能用堆栈(之前看矿斌的博客说堆栈可以加快最短路的速度,
但是这道题目不适用)。
三、注意结果用long long。
(3)代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL maxn = 2e5+10;
const LL INF = 1e9+10;
LL head[maxn],vis[maxn],dis[maxn],tim[maxn],tot,n,m,st[maxn<<2];
LL ans;
struct Node{
LL v,nxt,w;
}cur[maxn<<2];
void Init(){
memset(head,-1,sizeof(head));
tot = 0;
}
void Add(LL x,LL y,LL z){
cur[tot] = Node{y,head[x],z};
head[x] = tot++;
}
bool spfa(){
for(LL i=0;i<=n;i++){
dis[i] = -INF;vis[i] = 0;tim[i] = 0;
}
LL top = 0,rear = 0;
st[rear++] = 0;dis[0] = 0;tim[0]++;
while(top<rear){
LL x = st[top++];vis[x] = 0;
for(LL i=head[x];i!=-1;i=cur[i].nxt){
LL y = cur[i].v;
if(dis[y]<dis[x]+cur[i].w){
dis[y] = dis[x]+cur[i].w;
if(vis[y]==0){
vis[y] = 1;
if(++tim[y]>n) return false;
st[rear++] = y;
}
}
}
}
ans = 0;
for(LL i=1;i<=n;i++)
ans += dis[i];
return true;
}
inline void read(LL &x){
x = 0; char ch = getchar();
while (!isdigit(ch)) ch = getchar();
while (isdigit(ch)) x = (x * 10) + (ch & 15), ch = getchar();
}
int main(void){
Init();
read(n);read(m);
for(LL i=0;i<m;i++){
LL op,x,y;
read(op);read(x);read(y);
if(op==1){
Add(x,y,0);Add(y,x,0);
}
else if(op==2){
if(x==y){
printf("-1\n");
return 0;
}
Add(x,y,1);
}
else if(op==3){
Add(y,x,0);
}
else if(op==4){
if(x==y){
printf("-1\n");
return 0;
}
Add(y,x,1);
}
else if(op==5){
Add(x,y,0);
}
}
for(LL i=n;i>=1;i--) Add(0,i,1);
if(spfa()==false){
printf("-1\n");
return 0;
}
printf("%lld\n",ans);
return 0;
}