恩。。就是裸的差分约束。。
x=1 -> (A,B,0) (B,A,0)
x=2 -> (A,B,1) [这个情况加个A==B无解的要特判]
x=3 -> (B,A,0) [恩这个是不少于一开始zz建反了]
x=4 -> (B,A,1)
x=5 -> (A,B,0)
然后源点到所有点建1的边[恩据说有条链所以要反着连]跑最长路就好了
1 /* http://www.cnblogs.com/karl07/ */ 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 #include <cmath> 6 #include <algorithm> 7 #include <queue> 8 using namespace std; 9 10 const int N=100005; 11 struct edge{ 12 int next,to,v; 13 }e[N*4]; 14 15 int n,k,ade=0; 16 int first[N],dis[N],vis[N],tim[N]; 17 queue <int> q; 18 19 void addedge(int x,int y,int v){ 20 e[++ade].to=y; 21 e[ade].next=first[x]; 22 e[ade].v=v; 23 first[x]=ade; 24 } 25 26 #define s e[x].to 27 #define v e[x].v 28 long long spfa(){ 29 q.push(n+1),vis[n+1]=1; 30 while (!q.empty()){ 31 int p=q.front(); 32 q.pop(),vis[p]=0; 33 for (int x=first[p];x;x=e[x].next){ 34 if (dis[s]<dis[p]+v){ 35 dis[s]=dis[p]+v; 36 if (!vis[s]) vis[s]=1,q.push(s); 37 tim[s]++; 38 } 39 if (tim[s]>n+1) return -1; 40 } 41 } 42 long long ans=0; 43 for (int i=1;i<=n;i++) ans+=dis[i]; 44 return ans; 45 } 46 #undef v 47 #undef s 48 49 int main(){ 50 scanf("%d%d",&n,&k); 51 for (int i=1,a,b,x;i<=k;i++){ 52 scanf("%d%d%d",&x,&a,&b); 53 if (x==1) addedge(a,b,0),addedge(b,a,0); 54 if (x==2) if (a==b) {puts("-1"); return 0;} else addedge(a,b,1); 55 if (x==3) addedge(b,a,0); 56 if (x==4) if (a==b) {puts("-1"); return 0;} else addedge(b,a,1); 57 if (x==5) addedge(a,b,0); 58 } 59 for (int i=n;i>=1;i--) addedge(n+1,i,1); 60 printf("%lld\n",spfa()); 61 return 0; 62 } 63
蒟蒻退役前两天又开始更博客了。。期中考试和地理二模两个星期啥也没干。。然后明天就SHOI了。。
时间: 2024-11-05 03:09:09