poj1637Sightseeing tour

传送门

网络流解混合图欧拉回路,以前xy讲过,但是我一直没写。

把无向边随意定向,每个点权值为出度减入度,权值为奇数无解,权值大于0的从s向其连权值/2的边,小于0的向t连-权值/2的边,原图中无向图按定向连u->v权值为1的边,跑网络流判断是否满流即可,原图中的满流边即为要取反的边。

 

这两天先悠闲地整理一下前几天学的内容,过两天再开始全力准备noip吧大概。。

  1 //Achen
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<cstring>
  5 #include<cstdlib>
  6 #include<vector>
  7 #include<cstdio>
  8 #include<queue>
  9 #include<cmath>
 10 #include<set>
 11 #include<map>
 12 #define Formylove return 0
 13 #define For(i,a,b) for(int i=(a);i<=(b);i++)
 14 #define Rep(i,a,b) for(int i=(a);i>=(b);i--)
 15 const int N=4407;
 16 typedef long long LL;
 17 typedef double db;
 18 using namespace std;
 19 int n,m;
 20 
 21 template<typename T>void read(T &x)  {
 22     char ch=getchar(); x=0; T f=1;
 23     while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
 24     if(ch=='-') f=-1,ch=getchar();
 25     for(;ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0'; x*=f;
 26 }
 27 
 28 struct edge {
 29     int u,v,cap,fl,nx;
 30     edge(){}
 31     edge(int u,int v,int cap,int fl,int nx):u(u),v(v),cap(cap),fl(fl),nx(nx){} 
 32 }e[N];
 33 
 34 int ecnt=1,fir[N];
 35 void add(int u,int v,int cap) {
 36     e[++ecnt]=edge(u,v,cap,0,fir[u]); fir[u]=ecnt;
 37     //printf("%d->%d:%d\n",u,v,cap);
 38     e[++ecnt]=edge(v,u,0,0,fir[v]); fir[v]=ecnt;
 39 }
 40 
 41 queue<int>que;
 42 int d[N];
 43 void bfs(int s,int t) {
 44     que.push(t);
 45     For(i,1,n) d[i]=n;
 46     d[t]=0;
 47     while(!que.empty()) {
 48         int x=que.front();
 49         que.pop();
 50         for(int i=fir[x];i;i=e[i].nx) {
 51             int y=e[i].v;
 52             if(d[y]==n&&e[i].cap==0) {
 53                 d[y]=d[x]+1;
 54                 que.push(y); 
 55             }
 56         }
 57     }
 58 }
 59 
 60 #define inf 1e9
 61 int p[N];
 62 int calc(int s,int t) {
 63     int fl=inf;
 64     for(int i=t;i!=s;i=e[p[i]].u)
 65         fl=min(fl,e[p[i]].cap-e[p[i]].fl);
 66     for(int i=t;i!=s;i=e[p[i]].u) 
 67         e[p[i]].fl+=fl,e[p[i]^1].fl-=fl;
 68     return fl;
 69 }
 70 
 71 int c[N],cur[N];
 72 int isap(int s,int t) {
 73     For(i,0,n) c[i]=0;
 74     bfs(s,t);
 75     For(i,1,n) cur[i]=fir[i],c[d[i]]++;
 76     int rs=0;
 77     for(int x=s;d[x]<n;) {
 78         if(x==t) {
 79             rs+=calc(s,t);
 80             x=s;
 81         }
 82         int ok=0;
 83         for(int &i=cur[x];i;i=e[i].nx) if(e[i].cap>e[i].fl&&d[e[i].v]+1==d[x]) {
 84             ok=1; p[x=e[i].v]=i; break;
 85         }
 86         if(!ok) {
 87             int D=n; cur[x]=fir[x];
 88             for(int i=fir[x];i;i=e[i].nx) if(e[i].cap>e[i].fl)
 89                 D=min(D,d[e[i].v]+1);
 90             if(!(--c[d[x]])) break; 
 91             c[d[x]=D]++;
 92             if(x!=s) x=e[p[x]].u;
 93         }
 94     }
 95     return rs;
 96 }
 97 
 98 int dd[N];
 99 vector<int>vc;
100 void init() {
101     ecnt=1;
102     memset(fir,0,sizeof(fir));
103     memset(dd,0,sizeof(dd));
104 }
105 
106 int main() {
107 #ifdef ANS
108     freopen(".in","r",stdin);
109     freopen(".out","w",stdout);
110 #endif
111     int T; read(T);
112     while(T--) {
113         init();
114         read(n); read(m);
115         For(i,1,m) {
116             int u,v,w;
117             read(u); read(v); read(w);
118             dd[u]++; dd[v]--;
119             if(!w) add(u,v,1);
120         }
121         int s=n+1,t=n+2,fl=0; n+=2;
122         For(i,1,n-2) {
123             if(dd[i]&1) { fl=1; break; }
124             if(dd[i]>0) add(s,i,dd[i]/2); 
125             if(dd[i]<0) add(i,t,(-dd[i])/2);
126             if(dd[i]!=0) vc.push_back(ecnt-1); 
127         }
128         isap(s,t);
129         int up=vc.size();
130         For(i,0,up-1) if(e[vc[i]].fl!=e[vc[i]].cap) { 
131             fl=1; break; 
132         } vc.clear();
133         if(fl) puts("impossible");
134         else puts("possible");
135     }
136     Formylove;
137 }
View Code

 

转载于:https://www.cnblogs.com/Achenchen/p/9542745.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值