NOI模板复习组——图论部分
1.最小生成树:
kruscal:
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #define ll long long
- using namespace std;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- }edge[400005];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[400005];
- int f[200005];
- int head[200005];
- int cnt=1;
- int n,m;
- void init()
- {
- for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- int main()
- {
- read(n),read(m);
- init();
- for(int i=1;i<=m;i++)read(e[i].l),read(e[i].r),read(e[i].v);
- kruscal();
- return 0;
- }
2.最短路:
spfa(最好不要写,他死了)...
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #define ll long long
- using namespace std;
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- }edge[1000005];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[500005];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[200005];
- int head[200005];
- ll dis[200005];
- bool used[200005];
- int cnt=1;
- int n,m,S,T;
- void init()
- {
- for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- int main()
- {
- read(n),read(m),read(S);
- init();
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z;
- read(x),read(y),read(z);
- add(x,y,z);//,add(y,x,z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- //kruscal();
- spfa(S);
- //diji(S);
- return 0;
- }
dijisktra(这个比较好)
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #define ll long long
- using namespace std;
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- }edge[1000005];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[500005];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[200005];
- int head[200005];
- ll dis[200005];
- bool used[200005];
- int cnt=1;
- int n,m,S,T;
- void init()
- {
- for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- int main()
- {
- read(n),read(m),read(S);
- init();
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z;
- read(x),read(y),read(z);
- add(x,y,z);//,add(y,x,z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- //kruscal();
- //spfa(S);
- diji(S);
- return 0;
- }
3.LCA
倍增版本:
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #define ll long long
- using namespace std;
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- }edge[5000005];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[5000005];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[500005];
- int head[500005];
- ll dis[500005];
- int fa[500005][25];
- int dep[500005];
- int siz[500005],son[500005],ttop[500005];
- bool used[500005];
- int cnt=1;
- int n,m,S,T;
- void init()
- {
- for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void tree_dfs(int x,int fx)
- {
- dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
- for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- tree_dfs(to,x);
- siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
- }
- }
- void tree_redfs(int x,int topx,int fx)
- {
- ttop[x]=topx;
- if(son[x])tree_redfs(son[x],topx,x);
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx||to==son[x])continue;
- tree_redfs(to,to,x);
- }
- }
- int quick_jump_LCA(int x,int y)//倍增LCA
- {
- if(dep[x]>dep[y])swap(x,y);
- for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
- if(x==y)return x;
- int ret;
- for(int i=20;i>=0;i--)
- {
- if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
- else ret=fa[x][i];
- }
- return ret;
- }
- int link_cut_LCA(int x,int y)//树剖LCA
- {
- while(ttop[x]!=ttop[y])
- {
- if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
- x=fa[ttop[x]][0];
- }
- return dep[x]<dep[y]?x:y;
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- int main()
- {
- read(n),read(m),read(S);
- init();
- for(int i=1;i<n;i++)
- {
- int x,y;ll z;
- read(x),read(y);//,read(z);
- add(x,y,z),add(y,x,z);//,add(y,x,z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- //kruscal();
- //spfa(S);
- //diji(S);
- tree_dfs(S,S);//,tree_redfs(S,S,S);
- for(int i=1;i<=m;i++)
- {
- int x,y;
- read(x),read(y);
- printf("%d\n",quick_jump_LCA(x,y));
- }
- return 0;
- }
树剖版本:
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #define ll long long
- using namespace std;
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- }edge[5000005];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[5000005];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[500005];
- int head[500005];
- ll dis[500005];
- int fa[500005][25];
- int dep[500005];
- int siz[500005],son[500005],ttop[500005];
- bool used[500005];
- int cnt=1;
- int n,m,S,T;
- void init()
- {
- for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void tree_dfs(int x,int fx)
- {
- dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
- for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- tree_dfs(to,x);
- siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
- }
- }
- void tree_redfs(int x,int topx,int fx)
- {
- ttop[x]=topx;
- if(son[x])tree_redfs(son[x],topx,x);
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx||to==son[x])continue;
- tree_redfs(to,to,x);
- }
- }
- int quick_jump_LCA(int x,int y)//倍增LCA
- {
- if(dep[x]>dep[y])swap(x,y);
- for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
- if(x==y)return x;
- int ret;
- for(int i=20;i>=0;i--)
- {
- if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
- else ret=fa[x][i];
- }
- return ret;
- }
- int link_cut_LCA(int x,int y)//树剖LCA
- {
- while(ttop[x]!=ttop[y])
- {
- if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
- x=fa[ttop[x]][0];
- }
- return dep[x]<dep[y]?x:y;
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- int main()
- {
- read(n),read(m),read(S);
- init();
- for(int i=1;i<n;i++)
- {
- int x,y;ll z;
- read(x),read(y);//,read(z);
- add(x,y,z),add(y,x,z);//,add(y,x,z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- //kruscal();
- //spfa(S);
- //diji(S);
- tree_dfs(S,S),tree_redfs(S,S,S);
- for(int i=1;i<=m;i++)
- {
- int x,y;
- read(x),read(y);
- printf("%d\n",link_cut_LCA(x,y));
- }
- return 0;
- }
4.tarjan
有向图tarjan缩点+spfa最长路
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #include <vector>
- #define ll long long
- using namespace std;
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- }edge[5000005];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[5000005];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[500005];
- int head[500005];
- ll dis[500005];
- ll va[500005];
- int dfn[500005],low[500005],posi[500005];
- ll src_num[500005],src_cnt;
- int my_stack[500005],top=0;
- int fa[500005][25];
- int dep[500005];
- int spe[500005],nu;
- int siz[500005],son[500005],ttop[500005];
- bool used[500005];
- int cnt=1,deep;
- int n,m,S,T;
- vector <int> v[500005];
- void init()
- {
- for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void tree_dfs(int x,int fx)
- {
- dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
- for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- tree_dfs(to,x);
- siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
- }
- }
- void tree_redfs(int x,int topx,int fx)
- {
- ttop[x]=topx;
- if(son[x])tree_redfs(son[x],topx,x);
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx||to==son[x])continue;
- tree_redfs(to,to,x);
- }
- }
- int quick_jump_LCA(int x,int y)//倍增LCA
- {
- if(dep[x]>dep[y])swap(x,y);
- for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
- if(x==y)return x;
- int ret;
- for(int i=20;i>=0;i--)
- {
- if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
- else ret=fa[x][i];
- }
- return ret;
- }
- int link_cut_LCA(int x,int y)//树剖LCA
- {
- while(ttop[x]!=ttop[y])
- {
- if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
- x=fa[ttop[x]][0];
- }
- return dep[x]<dep[y]?x:y;
- }
- void tarjan(int x)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(!dfn[to])
- {
- tarjan(to);
- low[x]=min(low[x],low[to]);
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]+=va[t];
- posi[t]=src_cnt;
- }
- }
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void min_dis_spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- void max_dis_spfa(int st)
- {
- memset(dis,0,sizeof(dis));
- used[st]=1;
- dis[st]=src_num[st];
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=0;i<v[u].size();i++)
- {
- int to=v[u][i];
- if(dis[to]<dis[u]+src_num[to])
- {
- dis[to]=dis[u]+src_num[to];
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- ll ans=0;
- for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
- printf("%lld\n",ans);
- }
- void build_MST()
- {
- kruscal();
- }
- void get_min_dis_road()
- {
- //min_dis_spfa(S);
- diji(S);
- }
- void solve_LCA()
- {
- tree_dfs(S,S),tree_redfs(S,S,S);
- for(int i=1;i<=m;i++)
- {
- int x,y;
- read(x),read(y);
- printf("%d\n",link_cut_LCA(x,y));
- }
- }
- void direc_tarjan()//有向图tarjan
- {
- for(int i=1;i<=n;i++)read(va[i]);
- read(S),read(nu);
- for(int i=1;i<=nu;i++)read(spe[i]);
- for(int i=1;i<=n;i++)if(!dfn[i])tarjan(i);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]==posi[to])continue;
- else v[posi[i]].push_back(posi[to]);
- }
- }
- max_dis_spfa(posi[S]);
- }
- int main()
- {
- read(n),read(m);
- init();
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z;
- read(x),read(y);//,read(z);
- add(x,y,z);//,add(y,x,z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- direc_tarjan();
- return 0;
- }
无向图割边:
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #include <vector>
- #define ll long long
- using namespace std;
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- }edge[5000005];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[5000005];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[500005];
- int head[500005];
- ll dis[500005];
- ll va[500005];
- int dfn[500005],low[500005],posi[500005];
- ll src_num[500005],src_cnt;
- int my_stack[500005],top=0;
- int fa[500005][25];
- int dep[500005];
- int spe[500005],nu;
- int siz[500005],son[500005],ttop[500005];
- int inr[500005],our[500005];
- bool used[500005];
- int cnt=1,deep;
- int count_cut_line;
- int n,m,S,T;
- vector <int> v[500005];
- void init()
- {
- for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void tree_dfs(int x,int fx)
- {
- dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
- for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- tree_dfs(to,x);
- siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
- }
- }
- void tree_redfs(int x,int topx,int fx)
- {
- ttop[x]=topx;
- if(son[x])tree_redfs(son[x],topx,x);
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx||to==son[x])continue;
- tree_redfs(to,to,x);
- }
- }
- int quick_jump_LCA(int x,int y)//倍增LCA
- {
- if(dep[x]>dep[y])swap(x,y);
- for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
- if(x==y)return x;
- int ret;
- for(int i=20;i>=0;i--)
- {
- if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
- else ret=fa[x][i];
- }
- return ret;
- }
- int link_cut_LCA(int x,int y)//树剖LCA
- {
- while(ttop[x]!=ttop[y])
- {
- if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
- x=fa[ttop[x]][0];
- }
- return dep[x]<dep[y]?x:y;
- }
- void di_tarjan(int x)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(!dfn[to])
- {
- di_tarjan(to);
- low[x]=min(low[x],low[to]);
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]+=va[t];
- posi[t]=src_cnt;
- }
- }
- }
- void ed_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val==fx)continue;
- if(!dfn[to])
- {
- ed_tarjan(to,edge[i].val);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<low[to])count_cut_line++;
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]++;
- posi[t]=src_cnt;
- }
- }
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void min_dis_spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- void max_dis_spfa(int st)
- {
- memset(dis,0,sizeof(dis));
- used[st]=1;
- dis[st]=src_num[st];
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=0;i<v[u].size();i++)
- {
- int to=v[u][i];
- if(dis[to]<dis[u]+src_num[to])
- {
- dis[to]=dis[u]+src_num[to];
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- ll ans=0;
- for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
- printf("%lld\n",ans);
- }
- void build_MST()
- {
- kruscal();
- }
- void get_min_dis_road()
- {
- //min_dis_spfa(S);
- diji(S);
- }
- void solve_LCA()
- {
- tree_dfs(S,S),tree_redfs(S,S,S);
- for(int i=1;i<=m;i++)
- {
- int x,y;
- read(x),read(y);
- printf("%d\n",link_cut_LCA(x,y));
- }
- }
- void direc_tarjan()//有向图tarjan
- {
- for(int i=1;i<=n;i++)read(va[i]);
- read(S),read(nu);
- for(int i=1;i<=nu;i++)read(spe[i]);
- for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]==posi[to])continue;
- else v[posi[i]].push_back(posi[to]);
- }
- }
- max_dis_spfa(posi[S]);
- }
- void cut_line_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
- printf("%d ",count_cut_line);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]!=posi[to])inr[posi[to]]++;
- }
- }
- int s=0;
- for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
- printf("%d\n",(s+1)>>1);
- }
- int main()
- {
- read(n),read(m);
- init();
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z=i;
- read(x),read(y);//,read(z);
- add(x,y,z),add(y,x,z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- cut_line_tarjan();
- return 0;
- }
无向图割点:
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #include <vector>
- #define ll long long
- using namespace std;
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- }edge[5000005];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[5000005];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[500005];
- int head[500005];
- ll dis[500005];
- ll va[500005];
- int dfn[500005],low[500005],posi[500005];
- ll src_num[500005],src_cnt;
- int my_stack[500005],top=0;
- int fa[500005][25];
- int dep[500005];
- int spe[500005],nu;
- int siz[500005],son[500005],ttop[500005];
- int inr[500005],our[500005];
- bool used[500005];
- int cnt=1,deep;
- int count_cut_line;
- int n,m,S,T;
- vector <int> v[500005];
- vector <int> peo[500005];
- vector <int> cut_point;
- bool cmp(vector <int> a,vector <int> b)
- {
- int lim=min(a.size(),b.size());
- for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
- return a.size()<b.size();
- }
- void init()
- {
- for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void tree_dfs(int x,int fx)
- {
- dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
- for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- tree_dfs(to,x);
- siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
- }
- }
- void tree_redfs(int x,int topx,int fx)
- {
- ttop[x]=topx;
- if(son[x])tree_redfs(son[x],topx,x);
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx||to==son[x])continue;
- tree_redfs(to,to,x);
- }
- }
- int quick_jump_LCA(int x,int y)//倍增LCA
- {
- if(dep[x]>dep[y])swap(x,y);
- for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
- if(x==y)return x;
- int ret;
- for(int i=20;i>=0;i--)
- {
- if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
- else ret=fa[x][i];
- }
- return ret;
- }
- int link_cut_LCA(int x,int y)//树剖LCA
- {
- while(ttop[x]!=ttop[y])
- {
- if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
- x=fa[ttop[x]][0];
- }
- return dep[x]<dep[y]?x:y;
- }
- void di_tarjan(int x)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(!dfn[to])
- {
- di_tarjan(to);
- low[x]=min(low[x],low[to]);
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]+=va[t];
- posi[t]=src_cnt;
- }
- }
- }
- void ed_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val==fx)continue;
- if(!dfn[to])
- {
- ed_tarjan(to,edge[i].val);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<low[to])count_cut_line++;
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]++;
- posi[t]=src_cnt;
- }
- }
- }
- void po_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- if(!dfn[to])
- {
- int pre=top;
- po_tarjan(to,x);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<=low[to])
- {
- src_cnt++,posi[x]++;
- int t=0;
- while(top!=pre)
- {
- t=my_stack[top--];
- peo[src_cnt].push_back(t);
- }
- peo[src_cnt].push_back(x);
- sort(peo[src_cnt].begin(),peo[src_cnt].end());
- }
- }else low[x]=min(low[x],dfn[to]);
- }
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void min_dis_spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- void max_dis_spfa(int st)
- {
- memset(dis,0,sizeof(dis));
- used[st]=1;
- dis[st]=src_num[st];
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=0;i<v[u].size();i++)
- {
- int to=v[u][i];
- if(dis[to]<dis[u]+src_num[to])
- {
- dis[to]=dis[u]+src_num[to];
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- ll ans=0;
- for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
- printf("%lld\n",ans);
- }
- void build_MST()
- {
- kruscal();
- }
- void get_min_dis_road()
- {
- //min_dis_spfa(S);
- diji(S);
- }
- void solve_LCA()
- {
- tree_dfs(S,S),tree_redfs(S,S,S);
- for(int i=1;i<=m;i++)
- {
- int x,y;
- read(x),read(y);
- printf("%d\n",link_cut_LCA(x,y));
- }
- }
- void direc_tarjan()//有向图tarjan
- {
- for(int i=1;i<=n;i++)read(va[i]);
- read(S),read(nu);
- for(int i=1;i<=nu;i++)read(spe[i]);
- for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]==posi[to])continue;
- else v[posi[i]].push_back(posi[to]);
- }
- }
- max_dis_spfa(posi[S]);
- }
- void cut_line_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
- printf("%d ",count_cut_line);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]!=posi[to])inr[posi[to]]++;
- }
- }
- int s=0;
- for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
- printf("%d\n",(s+1)>>1);
- }
- void cut_point_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
- for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
- printf("%d\n",cut_point.size());
- for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
- printf("\n");
- printf("%d\n",src_cnt);
- sort(peo+1,peo+src_cnt+1,cmp);
- for(int i=1;i<=src_cnt;i++,printf("\n"))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
- }
- int main()
- {
- read(n),read(m);
- init();
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z=i;
- read(x),read(y);//,read(z);
- add(x,y,z),add(y,x,z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- cut_point_tarjan();
- return 0;
- }
5.网络流
最大流:
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #include <vector>
- #define ll long long
- using namespace std;
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- ll pri;
- }edge[5000005];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[5000005];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[500005];
- int head[500005];
- ll dis[500005];
- ll va[500005];
- int dfn[500005],low[500005],posi[500005];
- ll src_num[500005],src_cnt;
- int my_stack[500005],top=0;
- int fa[500005][25];
- int dep[500005];
- int spe[500005],nu;
- int siz[500005],son[500005],ttop[500005];
- int inr[500005],our[500005];
- int cur[500005];
- ll lim[500005];
- bool used[500005];
- int cnt=1,deep;
- int count_cut_line;
- int n,m,S,T;
- vector <int> v[500005];
- vector <int> peo[500005];
- vector <int> cut_point;
- bool cmp(vector <int> a,vector <int> b)
- {
- int lim=min(a.size(),b.size());
- for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
- return a.size()<b.size();
- }
- void init()
- {
- for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- void dadd(int l,int r,int w)
- {
- add(l,r,w),add(r,l,0);
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void tree_dfs(int x,int fx)
- {
- dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
- for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- tree_dfs(to,x);
- siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
- }
- }
- void tree_redfs(int x,int topx,int fx)
- {
- ttop[x]=topx;
- if(son[x])tree_redfs(son[x],topx,x);
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx||to==son[x])continue;
- tree_redfs(to,to,x);
- }
- }
- int quick_jump_LCA(int x,int y)//倍增LCA
- {
- if(dep[x]>dep[y])swap(x,y);
- for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
- if(x==y)return x;
- int ret;
- for(int i=20;i>=0;i--)
- {
- if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
- else ret=fa[x][i];
- }
- return ret;
- }
- int link_cut_LCA(int x,int y)//树剖LCA
- {
- while(ttop[x]!=ttop[y])
- {
- if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
- x=fa[ttop[x]][0];
- }
- return dep[x]<dep[y]?x:y;
- }
- void di_tarjan(int x)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(!dfn[to])
- {
- di_tarjan(to);
- low[x]=min(low[x],low[to]);
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]+=va[t];
- posi[t]=src_cnt;
- }
- }
- }
- void ed_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val==fx)continue;
- if(!dfn[to])
- {
- ed_tarjan(to,edge[i].val);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<low[to])count_cut_line++;
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]++;
- posi[t]=src_cnt;
- }
- }
- }
- void po_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- if(!dfn[to])
- {
- int pre=top;
- po_tarjan(to,x);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<=low[to])
- {
- src_cnt++,posi[x]++;
- int t=0;
- while(top!=pre)
- {
- t=my_stack[top--];
- peo[src_cnt].push_back(t);
- }
- peo[src_cnt].push_back(x);
- sort(peo[src_cnt].begin(),peo[src_cnt].end());
- }
- }else low[x]=min(low[x],dfn[to]);
- }
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void min_dis_spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- void max_dis_spfa(int st)
- {
- memset(dis,0,sizeof(dis));
- used[st]=1;
- dis[st]=src_num[st];
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=0;i<v[u].size();i++)
- {
- int to=v[u][i];
- if(dis[to]<dis[u]+src_num[to])
- {
- dis[to]=dis[u]+src_num[to];
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- ll ans=0;
- for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
- printf("%lld\n",ans);
- }
- void build_MST()
- {
- kruscal();
- }
- void get_min_dis_road()
- {
- //min_dis_spfa(S);
- diji(S);
- }
- void solve_LCA()
- {
- tree_dfs(S,S),tree_redfs(S,S,S);
- for(int i=1;i<=m;i++)
- {
- int x,y;
- read(x),read(y);
- printf("%d\n",link_cut_LCA(x,y));
- }
- }
- void direc_tarjan()//有向图tarjan
- {
- for(int i=1;i<=n;i++)read(va[i]);
- read(S),read(nu);
- for(int i=1;i<=nu;i++)read(spe[i]);
- for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]==posi[to])continue;
- else v[posi[i]].push_back(posi[to]);
- }
- }
- max_dis_spfa(posi[S]);
- }
- void cut_line_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
- printf("%d ",count_cut_line);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]!=posi[to])inr[posi[to]]++;
- }
- }
- int s=0;
- for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
- printf("%d\n",(s+1)>>1);
- }
- void cut_point_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
- for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
- printf("%d\n",cut_point.size());
- for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
- printf("\n");
- printf("%d\n",src_cnt);
- sort(peo+1,peo+src_cnt+1,cmp);
- for(int i=1;i<=src_cnt;i++,printf("\n"))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
- }
- int ide(int x)
- {
- return x&1?x+1:x-1;
- }
- bool dinic_bfs()
- {
- memset(dis,0,sizeof(dis));
- memcpy(cur,head,sizeof(head));
- dis[S]=1;
- queue <int> M;
- M.push(S);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
- }
- }
- return dis[T];
- }
- ll dinic_dfs(int x,ll lim)
- {
- if(x==T)return lim;
- ll ret=0;
- for(int i=cur[x];i;i=edge[i].nxt)
- {
- cur[x]=i;
- int to=edge[i].to;
- if(edge[i].val&&dis[to]==dis[x]+1)
- {
- ll temp=dinic_dfs(to,min(lim,edge[i].val));
- if(temp)
- {
- ret+=temp,lim-=temp;
- edge[i].val-=temp,edge[ide(i)].val+=temp;
- if(!lim)break;
- }
- }
- }
- return ret;
- }
- ll dinic()
- {
- ll ans=0;
- while(dinic_bfs())ans+=dinic_dfs(S,INF);
- return ans;
- }
- void max_flow()
- {
- printf("%lld\n",dinic());
- }
- int main()
- {
- read(n),read(m),read(S),read(T);
- init();
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z;
- read(x),read(y),read(z);
- dadd(x,y,z);//,add(y,x,z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- max_flow();
- return 0;
- }
费用流:
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #include <vector>
- #define ll long long
- using namespace std;
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- ll pri;
- }edge[5000005];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[5000005];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[500005];
- int head[500005];
- ll dis[500005];
- ll va[500005];
- int dfn[500005],low[500005],posi[500005];
- ll src_num[500005],src_cnt;
- int my_stack[500005],top=0;
- int fa[500005][25];
- int dep[500005];
- int spe[500005],nu;
- int siz[500005],son[500005],ttop[500005];
- int inr[500005],our[500005];
- int cur[500005];
- int pre[500005];
- ll lim[500005];
- bool used[500005];
- int cnt=1,deep;
- int count_cut_line;
- int n,m,S,T;
- vector <int> v[500005];
- vector <int> peo[500005];
- vector <int> cut_point;
- bool cmp(vector <int> a,vector <int> b)
- {
- int lim=min(a.size(),b.size());
- for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
- return a.size()<b.size();
- }
- void init()
- {
- for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- void dadd(int l,int r,int w)
- {
- add(l,r,w),add(r,l,0);
- }
- void cost_add(int l,int r,ll w,ll p)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- edge[cnt].pri=p;
- head[l]=cnt++;
- }
- void cost_dadd(int l,int r,ll w,ll p)
- {
- cost_add(l,r,w,p),cost_add(r,l,0,-p);
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void tree_dfs(int x,int fx)
- {
- dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
- for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- tree_dfs(to,x);
- siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
- }
- }
- void tree_redfs(int x,int topx,int fx)
- {
- ttop[x]=topx;
- if(son[x])tree_redfs(son[x],topx,x);
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx||to==son[x])continue;
- tree_redfs(to,to,x);
- }
- }
- int quick_jump_LCA(int x,int y)//倍增LCA
- {
- if(dep[x]>dep[y])swap(x,y);
- for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
- if(x==y)return x;
- int ret;
- for(int i=20;i>=0;i--)
- {
- if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
- else ret=fa[x][i];
- }
- return ret;
- }
- int link_cut_LCA(int x,int y)//树剖LCA
- {
- while(ttop[x]!=ttop[y])
- {
- if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
- x=fa[ttop[x]][0];
- }
- return dep[x]<dep[y]?x:y;
- }
- void di_tarjan(int x)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(!dfn[to])
- {
- di_tarjan(to);
- low[x]=min(low[x],low[to]);
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]+=va[t];
- posi[t]=src_cnt;
- }
- }
- }
- void ed_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val==fx)continue;
- if(!dfn[to])
- {
- ed_tarjan(to,edge[i].val);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<low[to])count_cut_line++;
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]++;
- posi[t]=src_cnt;
- }
- }
- }
- void po_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- if(!dfn[to])
- {
- int pre=top;
- po_tarjan(to,x);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<=low[to])
- {
- src_cnt++,posi[x]++;
- int t=0;
- while(top!=pre)
- {
- t=my_stack[top--];
- peo[src_cnt].push_back(t);
- }
- peo[src_cnt].push_back(x);
- sort(peo[src_cnt].begin(),peo[src_cnt].end());
- }
- }else low[x]=min(low[x],dfn[to]);
- }
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void min_dis_spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- void max_dis_spfa(int st)
- {
- memset(dis,0,sizeof(dis));
- used[st]=1;
- dis[st]=src_num[st];
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=0;i<v[u].size();i++)
- {
- int to=v[u][i];
- if(dis[to]<dis[u]+src_num[to])
- {
- dis[to]=dis[u]+src_num[to];
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- ll ans=0;
- for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
- printf("%lld\n",ans);
- }
- void build_MST()
- {
- kruscal();
- }
- void get_min_dis_road()
- {
- //min_dis_spfa(S);
- diji(S);
- }
- void solve_LCA()
- {
- tree_dfs(S,S),tree_redfs(S,S,S);
- for(int i=1;i<=m;i++)
- {
- int x,y;
- read(x),read(y);
- printf("%d\n",link_cut_LCA(x,y));
- }
- }
- void direc_tarjan()//有向图tarjan
- {
- for(int i=1;i<=n;i++)read(va[i]);
- read(S),read(nu);
- for(int i=1;i<=nu;i++)read(spe[i]);
- for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]==posi[to])continue;
- else v[posi[i]].push_back(posi[to]);
- }
- }
- max_dis_spfa(posi[S]);
- }
- void cut_line_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
- printf("%d ",count_cut_line);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]!=posi[to])inr[posi[to]]++;
- }
- }
- int s=0;
- for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
- printf("%d\n",(s+1)>>1);
- }
- void cut_point_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
- for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
- printf("%d\n",cut_point.size());
- for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
- printf("\n");
- printf("%d\n",src_cnt);
- sort(peo+1,peo+src_cnt+1,cmp);
- for(int i=1;i<=src_cnt;i++,printf("\n"))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
- }
- int ide(int x)
- {
- return x&1?x+1:x-1;
- }
- bool dinic_bfs()
- {
- memset(dis,0,sizeof(dis));
- memcpy(cur,head,sizeof(head));
- dis[S]=1;
- queue <int> M;
- M.push(S);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
- }
- }
- return dis[T];
- }
- ll dinic_dfs(int x,ll lim)
- {
- if(x==T)return lim;
- ll ret=0;
- for(int i=cur[x];i;i=edge[i].nxt)
- {
- cur[x]=i;
- int to=edge[i].to;
- if(edge[i].val&&dis[to]==dis[x]+1)
- {
- ll temp=dinic_dfs(to,min(lim,edge[i].val));
- if(temp)
- {
- ret+=temp,lim-=temp;
- edge[i].val-=temp,edge[ide(i)].val+=temp;
- if(!lim)break;
- }
- }
- }
- return ret;
- }
- ll dinic()
- {
- ll ans=0;
- while(dinic_bfs())ans+=dinic_dfs(S,INF);
- return ans;
- }
- void max_flow()
- {
- printf("%lld\n",dinic());
- }
- bool EK_spfa()
- {
- memset(pre,-1,sizeof(pre));
- memset(f,0,sizeof(f));
- memset(dis,0x3f,sizeof(dis));
- dis[S]=0,lim[S]=INF,used[S]=1;
- queue <int> M;
- M.push(S);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
- {
- dis[to]=dis[u]+edge[i].pri;
- pre[to]=i,f[to]=u,lim[to]=min(lim[u],edge[i].val);
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- return pre[T]!=-1;
- }
- void EK()
- {
- ll maxf=0,minv=0;
- while(EK_spfa())
- {
- maxf+=lim[T],minv+=dis[T]*lim[T];
- int temp=T;
- while(temp!=S)edge[pre[temp]].val-=lim[T],edge[ide(pre[temp])].val+=lim[T],temp=f[temp];
- }
- printf("%lld %lld\n",maxf,minv);
- }
- void min_cost_max_flow()
- {
- S=1,T=n;
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z,w;
- read(x),read(y),read(z),read(w);
- cost_dadd(x,y,z,w);
- }
- EK();
- }
- int main()
- {
- read(n),read(m);//,read(S),read(T);
- init();
- min_cost_max_flow();
- return 0;
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z;
- read(x),read(y),read(z);
- dadd(x,y,z);//,add(y,x,z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- max_flow();
- return 0;
- }
有源汇上下界最大流
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #include <vector>
- #define ll long long
- using namespace std;
- const int maxn=2000005;
- const int maxm=5000005;
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- ll pri;
- }edge[maxm];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[maxm];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[maxn];
- int head[maxn];
- ll dis[maxn];
- ll va[maxn];
- int dfn[maxn],low[maxn],posi[maxn];
- ll src_num[maxn],src_cnt;
- int my_stack[maxn],top=0;
- int fa[maxn][25];
- int dep[maxn];
- int spe[maxn],nu;
- int siz[maxn],son[maxn],ttop[maxn];
- int inr[maxn],our[maxn];
- int cur[maxn];
- int pre[maxn];
- ll lim[maxn];
- bool used[maxn];
- ll fin[maxn],fout[maxn];
- int cnt=1,deep;
- int count_cut_line;
- int n,m,S,T;
- vector <int> v[maxn];
- vector <int> peo[maxn];
- vector <int> cut_point;
- bool cmp(vector <int> a,vector <int> b)
- {
- int lim=min(a.size(),b.size());
- for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
- return a.size()<b.size();
- }
- void init()
- {
- //for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- void dadd(int l,int r,ll w)
- {
- add(l,r,w),add(r,l,0);
- }
- void cost_add(int l,int r,ll w,ll p)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- edge[cnt].pri=p;
- head[l]=cnt++;
- }
- void cost_dadd(int l,int r,ll w,ll p)
- {
- cost_add(l,r,w,p),cost_add(r,l,0,-p);
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void tree_dfs(int x,int fx)
- {
- dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
- for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- tree_dfs(to,x);
- siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
- }
- }
- void tree_redfs(int x,int topx,int fx)
- {
- ttop[x]=topx;
- if(son[x])tree_redfs(son[x],topx,x);
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx||to==son[x])continue;
- tree_redfs(to,to,x);
- }
- }
- int quick_jump_LCA(int x,int y)//倍增LCA
- {
- if(dep[x]>dep[y])swap(x,y);
- for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
- if(x==y)return x;
- int ret;
- for(int i=20;i>=0;i--)
- {
- if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
- else ret=fa[x][i];
- }
- return ret;
- }
- int link_cut_LCA(int x,int y)//树剖LCA
- {
- while(ttop[x]!=ttop[y])
- {
- if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
- x=fa[ttop[x]][0];
- }
- return dep[x]<dep[y]?x:y;
- }
- void di_tarjan(int x)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(!dfn[to])
- {
- di_tarjan(to);
- low[x]=min(low[x],low[to]);
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]++;
- posi[t]=src_cnt;
- }
- }
- }
- void ed_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val==fx)continue;
- if(!dfn[to])
- {
- ed_tarjan(to,edge[i].val);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<low[to])count_cut_line++;
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]++;
- posi[t]=src_cnt;
- }
- }
- }
- void po_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- if(!dfn[to])
- {
- int pre=top;
- po_tarjan(to,x);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<=low[to])
- {
- src_cnt++,posi[x]++;
- int t=0;
- while(top!=pre)
- {
- t=my_stack[top--];
- peo[src_cnt].push_back(t);
- }
- peo[src_cnt].push_back(x);
- sort(peo[src_cnt].begin(),peo[src_cnt].end());
- }
- }else low[x]=min(low[x],dfn[to]);
- }
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void min_dis_spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- void max_dis_spfa(int st)
- {
- memset(dis,0,sizeof(dis));
- used[st]=1;
- dis[st]=src_num[st];
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=0;i<v[u].size();i++)
- {
- int to=v[u][i];
- if(dis[to]<dis[u]+src_num[to])
- {
- dis[to]=dis[u]+src_num[to];
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- ll ans=0;
- for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
- printf("%lld\n",ans);
- }
- void build_MST()
- {
- kruscal();
- }
- void get_min_dis_road()
- {
- //min_dis_spfa(S);
- diji(S);
- }
- void solve_LCA()
- {
- tree_dfs(S,S),tree_redfs(S,S,S);
- for(int i=1;i<=m;i++)
- {
- int x,y;
- read(x),read(y);
- printf("%d\n",link_cut_LCA(x,y));
- }
- }
- void direc_tarjan()//有向图tarjan
- {
- for(int i=1;i<=n;i++)read(va[i]);
- read(S),read(nu);
- for(int i=1;i<=nu;i++)read(spe[i]);
- for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]==posi[to])continue;
- else v[posi[i]].push_back(posi[to]);
- }
- }
- max_dis_spfa(posi[S]);
- }
- void cut_line_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
- printf("%d ",count_cut_line);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]!=posi[to])inr[posi[to]]++;
- }
- }
- int s=0;
- for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
- printf("%d\n",(s+1)>>1);
- }
- void cut_point_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
- for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
- printf("%d\n",cut_point.size());
- for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
- printf("\n");
- printf("%d\n",src_cnt);
- sort(peo+1,peo+src_cnt+1,cmp);
- for(int i=1;i<=src_cnt;i++,printf("\n"))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
- }
- int ide(int x)
- {
- return x&1?x+1:x-1;
- }
- bool dinic_bfs()
- {
- memset(dis,0,sizeof(dis));
- memcpy(cur,head,sizeof(head));
- dis[S]=1;
- queue <int> M;
- M.push(S);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
- }
- }
- return dis[T];
- }
- ll dinic_dfs(int x,ll lim)
- {
- if(x==T)return lim;
- ll ret=0;
- for(int i=cur[x];i;i=edge[i].nxt)
- {
- cur[x]=i;
- int to=edge[i].to;
- if(edge[i].val&&dis[to]==dis[x]+1)
- {
- ll temp=dinic_dfs(to,min(lim,edge[i].val));
- if(temp)
- {
- ret+=temp,lim-=temp;
- edge[i].val-=temp,edge[ide(i)].val+=temp;
- if(!lim)break;
- }
- }
- }
- return ret;
- }
- ll dinic()
- {
- ll ans=0;
- while(dinic_bfs())ans+=dinic_dfs(S,INF);
- return ans;
- }
- void max_flow()
- {
- printf("%lld\n",dinic());
- }
- bool EK_spfa()
- {
- memset(pre,-1,sizeof(pre));
- memset(f,0,sizeof(f));
- memset(dis,0x3f,sizeof(dis));
- dis[S]=0,lim[S]=INF,used[S]=1;
- queue <int> M;
- M.push(S);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
- {
- dis[to]=dis[u]+edge[i].pri;
- pre[to]=i,f[to]=u,lim[to]=min(lim[u],edge[i].val);
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- return pre[T]!=-1;
- }
- void EK()
- {
- ll maxf=0,minv=0;
- while(EK_spfa())
- {
- maxf+=lim[T],minv+=dis[T]*lim[T];
- int temp=T;
- while(temp!=S)edge[pre[temp]].val-=lim[T],edge[ide(pre[temp])].val+=lim[T],temp=f[temp];
- }
- printf("%lld %lld\n",maxf,minv);
- }
- void min_cost_max_flow()
- {
- S=1,T=n;
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z,w;
- read(x),read(y),read(z),read(w);
- cost_dadd(x,y,z,w);
- }
- EK();
- }
- void two_SAT()
- {
- for(int i=1;i<=m;i++)
- {
- int x,y,z,w;
- read(x),read(y),read(z),read(w);
- if(y==1&&w==1)add(x+n,z,0),add(z+n,x,0);
- else if(y==1)add(x+n,z+n,0),add(z,x,0);
- else if(w==1)add(x,z,0),add(z+n,x+n,0);
- else add(x,z+n,0),add(z,x+n,0);
- }
- n<<=1;
- for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
- n>>=1;
- for(int i=1;i<=n;i++)if(posi[i]==posi[i+n]){printf("IMPOSSIBLE\n");exit(0);}
- printf("POSSIBLE\n");
- for(int i=1;i<=n;i++)
- {
- if(posi[i]<posi[i+n])printf("1 ");
- else printf("0 ");
- }
- printf("\n");
- }
- bool dfs(int x)
- {
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(used[to])continue;
- used[to]=1;
- if(!f[to]||dfs(f[to])){f[to]=x;return 1;}
- }
- return 0;
- }
- int hungary()
- {
- int ret=0;
- for(int i=1;i<=n;i++)
- {
- for(int j=1;j<=n+m;j++)used[j]=0;
- if(dfs(i))ret++;
- }
- return ret;
- }
- void two_match()
- {
- read(n),read(m),read(S);
- for(int i=1;i<=S;i++)
- {
- int x,y;
- read(x),read(y);
- if(x>n||y>m)continue;
- add(x,y+n,0),add(y+n,x,0);
- }
- printf("%d\n",hungary());
- }
- void upper_lower_maxflow()
- {
- int temps=S,tempt=T;
- S=n+1,T=n+2;
- ll sum=0;
- for(int i=1;i<=n;i++)
- {
- if(fin[i]>fout[i])dadd(S,i,fin[i]-fout[i]),sum+=fin[i]-fout[i];
- else dadd(i,T,fout[i]-fin[i]);
- }
- if(dinic()<sum)printf("please go home to sleep\n");
- else S=temps,T=tempt,printf("%lld\n",dinic());
- }
- void upper_lower_minflow()
- {
- int temps=S,tempt=T;
- S=n+1,T=n+2;
- ll sum=0;
- for(int i=1;i<=n;i++)
- {
- if(fin[i]>fout[i])dadd(S,i,fin[i]-fout[i]),sum+=fin[i]-fout[i];
- else dadd(i,T,fout[i]-fin[i]);
- }
- if(dinic()<sum)printf("please go home to sleep\n");
- else S=tempt,T=temps,printf("%lld\n",INF-dinic());
- }
- int main()
- {
- read(n),read(m),read(S),read(T);
- init();
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z,w;
- read(x),read(y),read(z),read(w);
- fin[y]+=z,fout[x]+=z;
- dadd(x,y,w-z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- dadd(T,S,INF);
- upper_lower_maxflow();
- return 0;
- }
有源汇上下界最小流
- #include <cstdio>
- #include <cmath>
- #include <cstring>
- #include <cstdlib>
- #include <iostream>
- #include <algorithm>
- #include <queue>
- #include <stack>
- #include <vector>
- #define ll long long
- using namespace std;
- const int maxn=2000005;
- const int maxm=5000005;
- template <typename T>inline void read(T &x)
- {
- T f=1,c=0;char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
- while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
- x=c*f;
- }
- const int inf=0x3f3f3f3f;
- const ll INF=0x3f3f3f3f3f3f3f3fll;
- struct Edge
- {
- int nxt;
- int to;
- ll val;
- ll pri;
- }edge[maxm];
- struct E
- {
- int l,r;
- ll v;
- friend bool operator < (E a,E b)
- {
- return a.v<b.v;
- }
- }e[maxm];
- struct node
- {
- int p;ll v;
- node (){}
- node (int x,ll y):p(x),v(y){}
- friend bool operator < (node a,node b)
- {
- return a.v>b.v;
- }
- };
- int f[maxn];
- int head[maxn];
- ll dis[maxn];
- ll va[maxn];
- int dfn[maxn],low[maxn],posi[maxn];
- ll src_num[maxn],src_cnt;
- int my_stack[maxn],top=0;
- int fa[maxn][25];
- int dep[maxn];
- int spe[maxn],nu;
- int siz[maxn],son[maxn],ttop[maxn];
- int inr[maxn],our[maxn];
- int cur[maxn];
- int pre[maxn];
- ll lim[maxn];
- bool used[maxn];
- ll fin[maxn],fout[maxn];
- int cnt=1,deep;
- int count_cut_line;
- int n,m,S,T;
- vector <int> v[maxn];
- vector <int> peo[maxn];
- vector <int> cut_point;
- bool cmp(vector <int> a,vector <int> b)
- {
- int lim=min(a.size(),b.size());
- for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
- return a.size()<b.size();
- }
- void init()
- {
- //for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
- cnt=1;
- }
- void add(int l,int r,ll w)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- head[l]=cnt++;
- }
- void dadd(int l,int r,ll w)
- {
- add(l,r,w),add(r,l,0);
- }
- void cost_add(int l,int r,ll w,ll p)
- {
- edge[cnt].nxt=head[l];
- edge[cnt].to=r;
- edge[cnt].val=w;
- edge[cnt].pri=p;
- head[l]=cnt++;
- }
- void cost_dadd(int l,int r,ll w,ll p)
- {
- cost_add(l,r,w,p),cost_add(r,l,0,-p);
- }
- int findf(int x)
- {
- return x==f[x]?x:f[x]=findf(f[x]);
- }
- void tree_dfs(int x,int fx)
- {
- dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
- for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- tree_dfs(to,x);
- siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
- }
- }
- void tree_redfs(int x,int topx,int fx)
- {
- ttop[x]=topx;
- if(son[x])tree_redfs(son[x],topx,x);
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx||to==son[x])continue;
- tree_redfs(to,to,x);
- }
- }
- int quick_jump_LCA(int x,int y)//倍增LCA
- {
- if(dep[x]>dep[y])swap(x,y);
- for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
- if(x==y)return x;
- int ret;
- for(int i=20;i>=0;i--)
- {
- if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
- else ret=fa[x][i];
- }
- return ret;
- }
- int link_cut_LCA(int x,int y)//树剖LCA
- {
- while(ttop[x]!=ttop[y])
- {
- if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
- x=fa[ttop[x]][0];
- }
- return dep[x]<dep[y]?x:y;
- }
- void di_tarjan(int x)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(!dfn[to])
- {
- di_tarjan(to);
- low[x]=min(low[x],low[to]);
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]++;
- posi[t]=src_cnt;
- }
- }
- }
- void ed_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val==fx)continue;
- if(!dfn[to])
- {
- ed_tarjan(to,edge[i].val);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<low[to])count_cut_line++;
- }else if(!posi[to])low[x]=min(low[x],dfn[to]);
- }
- if(dfn[x]==low[x])
- {
- src_cnt++;
- int t=0;
- while(t!=x)
- {
- t=my_stack[top--];
- src_num[src_cnt]++;
- posi[t]=src_cnt;
- }
- }
- }
- void po_tarjan(int x,int fx)
- {
- my_stack[++top]=x,dfn[x]=low[x]=++deep;
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(to==fx)continue;
- if(!dfn[to])
- {
- int pre=top;
- po_tarjan(to,x);
- low[x]=min(low[x],low[to]);
- if(dfn[x]<=low[to])
- {
- src_cnt++,posi[x]++;
- int t=0;
- while(top!=pre)
- {
- t=my_stack[top--];
- peo[src_cnt].push_back(t);
- }
- peo[src_cnt].push_back(x);
- sort(peo[src_cnt].begin(),peo[src_cnt].end());
- }
- }else low[x]=min(low[x],dfn[to]);
- }
- }
- void kruscal()
- {
- sort(e+1,e+m+1);
- int tot=0;ll ret=0;
- for(int i=1;i<=m;i++)
- {
- int f1=findf(e[i].l),f2=findf(e[i].r);
- if(f1==f2)continue;
- f[f1]=f2,tot++,ret+=e[i].v;
- if(tot==n-1)break;
- }
- if(tot==n-1)printf("%lld\n",ret);
- else printf("orz\n");
- }
- void min_dis_spfa(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0,used[st]=1;
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val)
- {
- dis[to]=dis[u]+edge[i].val;
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- for(int i=1;i<=n;i++)
- {
- if(dis[i]==INF)printf("2147483647 ");
- else printf("%lld ",dis[i]);
- }
- }
- void diji(int st)
- {
- memset(dis,0x3f,sizeof(dis));
- dis[st]=0;
- priority_queue <node> M;
- M.push(node(st,0));
- while(!M.empty())
- {
- node temp=M.top();
- M.pop();
- int u=temp.p;
- if(used[u])continue;
- used[u]=1;
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
- }
- }
- for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
- }
- void max_dis_spfa(int st)
- {
- memset(dis,0,sizeof(dis));
- used[st]=1;
- dis[st]=src_num[st];
- queue <int> M;
- M.push(st);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=0;i<v[u].size();i++)
- {
- int to=v[u][i];
- if(dis[to]<dis[u]+src_num[to])
- {
- dis[to]=dis[u]+src_num[to];
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- ll ans=0;
- for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
- printf("%lld\n",ans);
- }
- void build_MST()
- {
- kruscal();
- }
- void get_min_dis_road()
- {
- //min_dis_spfa(S);
- diji(S);
- }
- void solve_LCA()
- {
- tree_dfs(S,S),tree_redfs(S,S,S);
- for(int i=1;i<=m;i++)
- {
- int x,y;
- read(x),read(y);
- printf("%d\n",link_cut_LCA(x,y));
- }
- }
- void direc_tarjan()//有向图tarjan
- {
- for(int i=1;i<=n;i++)read(va[i]);
- read(S),read(nu);
- for(int i=1;i<=nu;i++)read(spe[i]);
- for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]==posi[to])continue;
- else v[posi[i]].push_back(posi[to]);
- }
- }
- max_dis_spfa(posi[S]);
- }
- void cut_line_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
- printf("%d ",count_cut_line);
- for(int i=1;i<=n;i++)
- {
- for(int j=head[i];j;j=edge[j].nxt)
- {
- int to=edge[j].to;
- if(posi[i]!=posi[to])inr[posi[to]]++;
- }
- }
- int s=0;
- for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
- printf("%d\n",(s+1)>>1);
- }
- void cut_point_tarjan()
- {
- for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
- for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
- printf("%d\n",cut_point.size());
- for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
- printf("\n");
- printf("%d\n",src_cnt);
- sort(peo+1,peo+src_cnt+1,cmp);
- for(int i=1;i<=src_cnt;i++,printf("\n"))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
- }
- int ide(int x)
- {
- return x&1?x+1:x-1;
- }
- bool dinic_bfs()
- {
- memset(dis,0,sizeof(dis));
- memcpy(cur,head,sizeof(head));
- dis[S]=1;
- queue <int> M;
- M.push(S);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
- }
- }
- return dis[T];
- }
- ll dinic_dfs(int x,ll lim)
- {
- if(x==T)return lim;
- ll ret=0;
- for(int i=cur[x];i;i=edge[i].nxt)
- {
- cur[x]=i;
- int to=edge[i].to;
- if(edge[i].val&&dis[to]==dis[x]+1)
- {
- ll temp=dinic_dfs(to,min(lim,edge[i].val));
- if(temp)
- {
- ret+=temp,lim-=temp;
- edge[i].val-=temp,edge[ide(i)].val+=temp;
- if(!lim)break;
- }
- }
- }
- return ret;
- }
- ll dinic()
- {
- ll ans=0;
- while(dinic_bfs())ans+=dinic_dfs(S,INF);
- return ans;
- }
- void max_flow()
- {
- printf("%lld\n",dinic());
- }
- bool EK_spfa()
- {
- memset(pre,-1,sizeof(pre));
- memset(f,0,sizeof(f));
- memset(dis,0x3f,sizeof(dis));
- dis[S]=0,lim[S]=INF,used[S]=1;
- queue <int> M;
- M.push(S);
- while(!M.empty())
- {
- int u=M.front();
- M.pop();
- for(int i=head[u];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
- {
- dis[to]=dis[u]+edge[i].pri;
- pre[to]=i,f[to]=u,lim[to]=min(lim[u],edge[i].val);
- if(!used[to])used[to]=1,M.push(to);
- }
- }
- used[u]=0;
- }
- return pre[T]!=-1;
- }
- void EK()
- {
- ll maxf=0,minv=0;
- while(EK_spfa())
- {
- maxf+=lim[T],minv+=dis[T]*lim[T];
- int temp=T;
- while(temp!=S)edge[pre[temp]].val-=lim[T],edge[ide(pre[temp])].val+=lim[T],temp=f[temp];
- }
- printf("%lld %lld\n",maxf,minv);
- }
- void min_cost_max_flow()
- {
- S=1,T=n;
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z,w;
- read(x),read(y),read(z),read(w);
- cost_dadd(x,y,z,w);
- }
- EK();
- }
- void two_SAT()
- {
- for(int i=1;i<=m;i++)
- {
- int x,y,z,w;
- read(x),read(y),read(z),read(w);
- if(y==1&&w==1)add(x+n,z,0),add(z+n,x,0);
- else if(y==1)add(x+n,z+n,0),add(z,x,0);
- else if(w==1)add(x,z,0),add(z+n,x+n,0);
- else add(x,z+n,0),add(z,x+n,0);
- }
- n<<=1;
- for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
- n>>=1;
- for(int i=1;i<=n;i++)if(posi[i]==posi[i+n]){printf("IMPOSSIBLE\n");exit(0);}
- printf("POSSIBLE\n");
- for(int i=1;i<=n;i++)
- {
- if(posi[i]<posi[i+n])printf("1 ");
- else printf("0 ");
- }
- printf("\n");
- }
- bool dfs(int x)
- {
- for(int i=head[x];i;i=edge[i].nxt)
- {
- int to=edge[i].to;
- if(used[to])continue;
- used[to]=1;
- if(!f[to]||dfs(f[to])){f[to]=x;return 1;}
- }
- return 0;
- }
- int hungary()
- {
- int ret=0;
- for(int i=1;i<=n;i++)
- {
- for(int j=1;j<=n+m;j++)used[j]=0;
- if(dfs(i))ret++;
- }
- return ret;
- }
- void two_match()
- {
- read(n),read(m),read(S);
- for(int i=1;i<=S;i++)
- {
- int x,y;
- read(x),read(y);
- if(x>n||y>m)continue;
- add(x,y+n,0),add(y+n,x,0);
- }
- printf("%d\n",hungary());
- }
- void upper_lower_maxflow()
- {
- int temps=S,tempt=T;
- S=n+1,T=n+2;
- ll sum=0;
- for(int i=1;i<=n;i++)
- {
- if(fin[i]>fout[i])dadd(S,i,fin[i]-fout[i]),sum+=fin[i]-fout[i];
- else dadd(i,T,fout[i]-fin[i]);
- }
- if(dinic()<sum)printf("please go home to sleep\n");
- else S=temps,T=tempt,printf("%lld\n",dinic());
- }
- void upper_lower_minflow()
- {
- int temps=S,tempt=T;
- S=n+1,T=n+2;
- ll sum=0;
- for(int i=1;i<=n;i++)
- {
- if(fin[i]>fout[i])dadd(S,i,fin[i]-fout[i]),sum+=fin[i]-fout[i];
- else dadd(i,T,fout[i]-fin[i]);
- }
- if(dinic()<sum)printf("please go home to sleep\n");
- else S=tempt,T=temps,printf("%lld\n",INF-dinic());
- }
- int main()
- {
- read(n),read(m),read(S),read(T);
- init();
- for(int i=1;i<=m;i++)
- {
- int x,y;ll z,w;
- read(x),read(y),read(z),read(w);
- fin[y]+=z,fout[x]+=z;
- dadd(x,y,w-z);
- e[i].l=x,e[i].r=y,e[i].v=z;
- }
- dadd(T,S,INF);
- upper_lower_minflow();
- return 0;
- }
6.2-SAT
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#define ll long long
using namespace std;
const int maxn=2000005;
const int maxm=5000005;
template <typename T>inline void read(T &x)
{
T f=1,c=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
x=c*f;
}
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
struct Edge
{
int nxt;
int to;
ll val;
ll pri;
}edge[maxm];
struct E
{
int l,r;
ll v;
friend bool operator < (E a,E b)
{
return a.v<b.v;
}
}e[maxm];
struct node
{
int p;ll v;
node (){}
node (int x,ll y):p(x),v(y){}
friend bool operator < (node a,node b)
{
return a.v>b.v;
}
};
int f[maxn];
int head[maxn];
ll dis[maxn];
ll va[maxn];
int dfn[maxn],low[maxn],posi[maxn];
ll src_num[maxn],src_cnt;
int my_stack[maxn],top=0;
int fa[maxn][25];
int dep[maxn];
int spe[maxn],nu;
int siz[maxn],son[maxn],ttop[maxn];
int inr[maxn],our[maxn];
int cur[maxn];
int pre[maxn];
ll lim[maxn];
bool used[maxn];
int cnt=1,deep;
int count_cut_line;
int n,m,S,T;
vector <int> v[maxn];
vector <int> peo[maxn];
vector <int> cut_point;
bool cmp(vector <int> a,vector <int> b)
{
int lim=min(a.size(),b.size());
for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
return a.size()<b.size();
}
void init()
{
//for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
cnt=1;
}
void add(int l,int r,ll w)
{
edge[cnt].nxt=head[l];
edge[cnt].to=r;
edge[cnt].val=w;
head[l]=cnt++;
}
void dadd(int l,int r,int w)
{
add(l,r,w),add(r,l,0);
}
void cost_add(int l,int r,ll w,ll p)
{
edge[cnt].nxt=head[l];
edge[cnt].to=r;
edge[cnt].val=w;
edge[cnt].pri=p;
head[l]=cnt++;
}
void cost_dadd(int l,int r,ll w,ll p)
{
cost_add(l,r,w,p),cost_add(r,l,0,-p);
}
int findf(int x)
{
return x==f[x]?x:f[x]=findf(f[x]);
}
void tree_dfs(int x,int fx)
{
dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx)continue;
tree_dfs(to,x);
siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
}
}
void tree_redfs(int x,int topx,int fx)
{
ttop[x]=topx;
if(son[x])tree_redfs(son[x],topx,x);
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx||to==son[x])continue;
tree_redfs(to,to,x);
}
}
int quick_jump_LCA(int x,int y)//倍增LCA
{
if(dep[x]>dep[y])swap(x,y);
for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
if(x==y)return x;
int ret;
for(int i=20;i>=0;i--)
{
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
else ret=fa[x][i];
}
return ret;
}
int link_cut_LCA(int x,int y)//树剖LCA
{
while(ttop[x]!=ttop[y])
{
if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
x=fa[ttop[x]][0];
}
return dep[x]<dep[y]?x:y;
}
void di_tarjan(int x)
{
my_stack[++top]=x,dfn[x]=low[x]=++deep;
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(!dfn[to])
{
di_tarjan(to);
low[x]=min(low[x],low[to]);
}else if(!posi[to])low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x])
{
src_cnt++;
int t=0;
while(t!=x)
{
t=my_stack[top--];
src_num[src_cnt]++;
posi[t]=src_cnt;
}
}
}
void ed_tarjan(int x,int fx)
{
my_stack[++top]=x,dfn[x]=low[x]=++deep;
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(edge[i].val==fx)continue;
if(!dfn[to])
{
ed_tarjan(to,edge[i].val);
low[x]=min(low[x],low[to]);
if(dfn[x]<low[to])count_cut_line++;
}else if(!posi[to])low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x])
{
src_cnt++;
int t=0;
while(t!=x)
{
t=my_stack[top--];
src_num[src_cnt]++;
posi[t]=src_cnt;
}
}
}
void po_tarjan(int x,int fx)
{
my_stack[++top]=x,dfn[x]=low[x]=++deep;
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx)continue;
if(!dfn[to])
{
int pre=top;
po_tarjan(to,x);
low[x]=min(low[x],low[to]);
if(dfn[x]<=low[to])
{
src_cnt++,posi[x]++;
int t=0;
while(top!=pre)
{
t=my_stack[top--];
peo[src_cnt].push_back(t);
}
peo[src_cnt].push_back(x);
sort(peo[src_cnt].begin(),peo[src_cnt].end());
}
}else low[x]=min(low[x],dfn[to]);
}
}
void kruscal()
{
sort(e+1,e+m+1);
int tot=0;ll ret=0;
for(int i=1;i<=m;i++)
{
int f1=findf(e[i].l),f2=findf(e[i].r);
if(f1==f2)continue;
f[f1]=f2,tot++,ret+=e[i].v;
if(tot==n-1)break;
}
if(tot==n-1)printf("%lld\n",ret);
else printf("orz\n");
}
void min_dis_spfa(int st)
{
memset(dis,0x3f,sizeof(dis));
dis[st]=0,used[st]=1;
queue <int> M;
M.push(st);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(dis[to]>dis[u]+edge[i].val)
{
dis[to]=dis[u]+edge[i].val;
if(!used[to])used[to]=1,M.push(to);
}
}
used[u]=0;
}
for(int i=1;i<=n;i++)
{
if(dis[i]==INF)printf("2147483647 ");
else printf("%lld ",dis[i]);
}
}
void diji(int st)
{
memset(dis,0x3f,sizeof(dis));
dis[st]=0;
priority_queue <node> M;
M.push(node(st,0));
while(!M.empty())
{
node temp=M.top();
M.pop();
int u=temp.p;
if(used[u])continue;
used[u]=1;
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
}
}
for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
}
void max_dis_spfa(int st)
{
memset(dis,0,sizeof(dis));
used[st]=1;
dis[st]=src_num[st];
queue <int> M;
M.push(st);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=0;i<v[u].size();i++)
{
int to=v[u][i];
if(dis[to]<dis[u]+src_num[to])
{
dis[to]=dis[u]+src_num[to];
if(!used[to])used[to]=1,M.push(to);
}
}
used[u]=0;
}
ll ans=0;
for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
printf("%lld\n",ans);
}
void build_MST()
{
kruscal();
}
void get_min_dis_road()
{
//min_dis_spfa(S);
diji(S);
}
void solve_LCA()
{
tree_dfs(S,S),tree_redfs(S,S,S);
for(int i=1;i<=m;i++)
{
int x,y;
read(x),read(y);
printf("%d\n",link_cut_LCA(x,y));
}
}
void direc_tarjan()//有向图tarjan
{
for(int i=1;i<=n;i++)read(va[i]);
read(S),read(nu);
for(int i=1;i<=nu;i++)read(spe[i]);
for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
for(int i=1;i<=n;i++)
{
for(int j=head[i];j;j=edge[j].nxt)
{
int to=edge[j].to;
if(posi[i]==posi[to])continue;
else v[posi[i]].push_back(posi[to]);
}
}
max_dis_spfa(posi[S]);
}
void cut_line_tarjan()
{
for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
printf("%d ",count_cut_line);
for(int i=1;i<=n;i++)
{
for(int j=head[i];j;j=edge[j].nxt)
{
int to=edge[j].to;
if(posi[i]!=posi[to])inr[posi[to]]++;
}
}
int s=0;
for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
printf("%d\n",(s+1)>>1);
}
void cut_point_tarjan()
{
for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
printf("%d\n",cut_point.size());
for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
printf("\n");
printf("%d\n",src_cnt);
sort(peo+1,peo+src_cnt+1,cmp);
for(int i=1;i<=src_cnt;i++,printf("\n"))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
}
int ide(int x)
{
return x&1?x+1:x-1;
}
bool dinic_bfs()
{
memset(dis,0,sizeof(dis));
memcpy(cur,head,sizeof(head));
dis[S]=1;
queue <int> M;
M.push(S);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
}
}
return dis[T];
}
ll dinic_dfs(int x,ll lim)
{
if(x==T)return lim;
ll ret=0;
for(int i=cur[x];i;i=edge[i].nxt)
{
cur[x]=i;
int to=edge[i].to;
if(edge[i].val&&dis[to]==dis[x]+1)
{
ll temp=dinic_dfs(to,min(lim,edge[i].val));
if(temp)
{
ret+=temp,lim-=temp;
edge[i].val-=temp,edge[ide(i)].val+=temp;
if(!lim)break;
}
}
}
return ret;
}
ll dinic()
{
ll ans=0;
while(dinic_bfs())ans+=dinic_dfs(S,INF);
return ans;
}
void max_flow()
{
printf("%lld\n",dinic());
}
bool EK_spfa()
{
memset(pre,-1,sizeof(pre));
memset(f,0,sizeof(f));
memset(dis,0x3f,sizeof(dis));
dis[S]=0,lim[S]=INF,used[S]=1;
queue <int> M;
M.push(S);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
{
dis[to]=dis[u]+edge[i].pri;
pre[to]=i,f[to]=u,lim[to]=min(lim[u],edge[i].val);
if(!used[to])used[to]=1,M.push(to);
}
}
used[u]=0;
}
return pre[T]!=-1;
}
void EK()
{
ll maxf=0,minv=0;
while(EK_spfa())
{
maxf+=lim[T],minv+=dis[T]*lim[T];
int temp=T;
while(temp!=S)edge[pre[temp]].val-=lim[T],edge[ide(pre[temp])].val+=lim[T],temp=f[temp];
}
printf("%lld %lld\n",maxf,minv);
}
void min_cost_max_flow()
{
S=1,T=n;
for(int i=1;i<=m;i++)
{
int x,y;ll z,w;
read(x),read(y),read(z),read(w);
cost_dadd(x,y,z,w);
}
EK();
}
void two_SAT()
{
for(int i=1;i<=m;i++)
{
int x,y,z,w;
read(x),read(y),read(z),read(w);
if(y==1&&w==1)add(x+n,z,0),add(z+n,x,0);
else if(y==1)add(x+n,z+n,0),add(z,x,0);
else if(w==1)add(x,z,0),add(z+n,x+n,0);
else add(x,z+n,0),add(z,x+n,0);
}
n<<=1;
for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
n>>=1;
for(int i=1;i<=n;i++)if(posi[i]==posi[i+n]){printf("IMPOSSIBLE\n");exit(0);}
printf("POSSIBLE\n");
for(int i=1;i<=n;i++)
{
if(posi[i]<posi[i+n])printf("1 ");
else printf("0 ");
}
printf("\n");
}
int main()
{
read(n),read(m)//,read(S),read(T);
init();
two_SAT();
return 0;
for(int i=1;i<=m;i++)
{
int x,y;ll z;
read(x),read(y),read(z);
dadd(x,y,z);//,add(y,x,z);
e[i].l=x,e[i].r=y,e[i].v=z;
}
return 0;
}
7.二分图匹配(匈牙利)
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#define ll long long
using namespace std;
const int maxn=2000005;
const int maxm=5000005;
template <typename T>inline void read(T &x)
{
T f=1,c=0;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();}
x=c*f;
}
const int inf=0x3f3f3f3f;
const ll INF=0x3f3f3f3f3f3f3f3fll;
struct Edge
{
int nxt;
int to;
ll val;
ll pri;
}edge[maxm];
struct E
{
int l,r;
ll v;
friend bool operator < (E a,E b)
{
return a.v<b.v;
}
}e[maxm];
struct node
{
int p;ll v;
node (){}
node (int x,ll y):p(x),v(y){}
friend bool operator < (node a,node b)
{
return a.v>b.v;
}
};
int f[maxn];
int head[maxn];
ll dis[maxn];
ll va[maxn];
int dfn[maxn],low[maxn],posi[maxn];
ll src_num[maxn],src_cnt;
int my_stack[maxn],top=0;
int fa[maxn][25];
int dep[maxn];
int spe[maxn],nu;
int siz[maxn],son[maxn],ttop[maxn];
int inr[maxn],our[maxn];
int cur[maxn];
int pre[maxn];
ll lim[maxn];
bool used[maxn];
int cnt=1,deep;
int count_cut_line;
int n,m,S,T;
vector <int> v[maxn];
vector <int> peo[maxn];
vector <int> cut_point;
bool cmp(vector <int> a,vector <int> b)
{
int lim=min(a.size(),b.size());
for(int i=0;i<lim;i++)if(a[i]!=b[i])return a[i]<b[i];
return a.size()<b.size();
}
void init()
{
//for(int i=1;i<=n;i++)f[i]=i,head[i]=0;
cnt=1;
}
void add(int l,int r,ll w)
{
edge[cnt].nxt=head[l];
edge[cnt].to=r;
edge[cnt].val=w;
head[l]=cnt++;
}
void dadd(int l,int r,int w)
{
add(l,r,w),add(r,l,0);
}
void cost_add(int l,int r,ll w,ll p)
{
edge[cnt].nxt=head[l];
edge[cnt].to=r;
edge[cnt].val=w;
edge[cnt].pri=p;
head[l]=cnt++;
}
void cost_dadd(int l,int r,ll w,ll p)
{
cost_add(l,r,w,p),cost_add(r,l,0,-p);
}
int findf(int x)
{
return x==f[x]?x:f[x]=findf(f[x]);
}
void tree_dfs(int x,int fx)
{
dep[x]=dep[fx]+1,siz[x]=1,fa[x][0]=fx;
for(int i=1;i<=20;i++)fa[x][i]=fa[fa[x][i-1]][i-1];
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx)continue;
tree_dfs(to,x);
siz[x]+=siz[to],son[x]=(siz[son[x]]>siz[to])?son[x]:to;
}
}
void tree_redfs(int x,int topx,int fx)
{
ttop[x]=topx;
if(son[x])tree_redfs(son[x],topx,x);
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx||to==son[x])continue;
tree_redfs(to,to,x);
}
}
int quick_jump_LCA(int x,int y)//倍增LCA
{
if(dep[x]>dep[y])swap(x,y);
for(int i=20;i>=0;i--)if(dep[fa[y][i]]>=dep[x])y=fa[y][i];
if(x==y)return x;
int ret;
for(int i=20;i>=0;i--)
{
if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
else ret=fa[x][i];
}
return ret;
}
int link_cut_LCA(int x,int y)//树剖LCA
{
while(ttop[x]!=ttop[y])
{
if(dep[ttop[x]]<dep[ttop[y]])swap(x,y);
x=fa[ttop[x]][0];
}
return dep[x]<dep[y]?x:y;
}
void di_tarjan(int x)
{
my_stack[++top]=x,dfn[x]=low[x]=++deep;
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(!dfn[to])
{
di_tarjan(to);
low[x]=min(low[x],low[to]);
}else if(!posi[to])low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x])
{
src_cnt++;
int t=0;
while(t!=x)
{
t=my_stack[top--];
src_num[src_cnt]++;
posi[t]=src_cnt;
}
}
}
void ed_tarjan(int x,int fx)
{
my_stack[++top]=x,dfn[x]=low[x]=++deep;
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(edge[i].val==fx)continue;
if(!dfn[to])
{
ed_tarjan(to,edge[i].val);
low[x]=min(low[x],low[to]);
if(dfn[x]<low[to])count_cut_line++;
}else if(!posi[to])low[x]=min(low[x],dfn[to]);
}
if(dfn[x]==low[x])
{
src_cnt++;
int t=0;
while(t!=x)
{
t=my_stack[top--];
src_num[src_cnt]++;
posi[t]=src_cnt;
}
}
}
void po_tarjan(int x,int fx)
{
my_stack[++top]=x,dfn[x]=low[x]=++deep;
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(to==fx)continue;
if(!dfn[to])
{
int pre=top;
po_tarjan(to,x);
low[x]=min(low[x],low[to]);
if(dfn[x]<=low[to])
{
src_cnt++,posi[x]++;
int t=0;
while(top!=pre)
{
t=my_stack[top--];
peo[src_cnt].push_back(t);
}
peo[src_cnt].push_back(x);
sort(peo[src_cnt].begin(),peo[src_cnt].end());
}
}else low[x]=min(low[x],dfn[to]);
}
}
void kruscal()
{
sort(e+1,e+m+1);
int tot=0;ll ret=0;
for(int i=1;i<=m;i++)
{
int f1=findf(e[i].l),f2=findf(e[i].r);
if(f1==f2)continue;
f[f1]=f2,tot++,ret+=e[i].v;
if(tot==n-1)break;
}
if(tot==n-1)printf("%lld\n",ret);
else printf("orz\n");
}
void min_dis_spfa(int st)
{
memset(dis,0x3f,sizeof(dis));
dis[st]=0,used[st]=1;
queue <int> M;
M.push(st);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(dis[to]>dis[u]+edge[i].val)
{
dis[to]=dis[u]+edge[i].val;
if(!used[to])used[to]=1,M.push(to);
}
}
used[u]=0;
}
for(int i=1;i<=n;i++)
{
if(dis[i]==INF)printf("2147483647 ");
else printf("%lld ",dis[i]);
}
}
void diji(int st)
{
memset(dis,0x3f,sizeof(dis));
dis[st]=0;
priority_queue <node> M;
M.push(node(st,0));
while(!M.empty())
{
node temp=M.top();
M.pop();
int u=temp.p;
if(used[u])continue;
used[u]=1;
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(dis[to]>dis[u]+edge[i].val&&!used[to])dis[to]=dis[u]+edge[i].val,M.push(node(to,dis[to]));
}
}
for(int i=1;i<=n;i++)printf("%lld ",dis[i]);
}
void max_dis_spfa(int st)
{
memset(dis,0,sizeof(dis));
used[st]=1;
dis[st]=src_num[st];
queue <int> M;
M.push(st);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=0;i<v[u].size();i++)
{
int to=v[u][i];
if(dis[to]<dis[u]+src_num[to])
{
dis[to]=dis[u]+src_num[to];
if(!used[to])used[to]=1,M.push(to);
}
}
used[u]=0;
}
ll ans=0;
for(int i=1;i<=nu;i++)ans=max(ans,dis[posi[spe[i]]]);
printf("%lld\n",ans);
}
void build_MST()
{
kruscal();
}
void get_min_dis_road()
{
//min_dis_spfa(S);
diji(S);
}
void solve_LCA()
{
tree_dfs(S,S),tree_redfs(S,S,S);
for(int i=1;i<=m;i++)
{
int x,y;
read(x),read(y);
printf("%d\n",link_cut_LCA(x,y));
}
}
void direc_tarjan()//有向图tarjan
{
for(int i=1;i<=n;i++)read(va[i]);
read(S),read(nu);
for(int i=1;i<=nu;i++)read(spe[i]);
for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
for(int i=1;i<=n;i++)
{
for(int j=head[i];j;j=edge[j].nxt)
{
int to=edge[j].to;
if(posi[i]==posi[to])continue;
else v[posi[i]].push_back(posi[to]);
}
}
max_dis_spfa(posi[S]);
}
void cut_line_tarjan()
{
for(int i=1;i<=n;i++)if(!dfn[i])ed_tarjan(i,-1);
printf("%d ",count_cut_line);
for(int i=1;i<=n;i++)
{
for(int j=head[i];j;j=edge[j].nxt)
{
int to=edge[j].to;
if(posi[i]!=posi[to])inr[posi[to]]++;
}
}
int s=0;
for(int i=1;i<=src_cnt;i++)if(inr[i]==1)s++;
printf("%d\n",(s+1)>>1);
}
void cut_point_tarjan()
{
for(int i=1;i<=n;i++)if(!dfn[i])po_tarjan(i,-1),posi[i]--;
for(int i=1;i<=n;i++)if(posi[i]>=1)cut_point.push_back(i);
printf("%d\n",cut_point.size());
for(int i=0;i<cut_point.size();i++)printf("%d ",cut_point[i]);
printf("\n");
printf("%d\n",src_cnt);
sort(peo+1,peo+src_cnt+1,cmp);
for(int i=1;i<=src_cnt;i++,printf("\n"))for(int j=0;j<peo[i].size();j++)printf("%d ",peo[i][j]);
}
int ide(int x)
{
return x&1?x+1:x-1;
}
bool dinic_bfs()
{
memset(dis,0,sizeof(dis));
memcpy(cur,head,sizeof(head));
dis[S]=1;
queue <int> M;
M.push(S);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(edge[i].val&&!dis[to])dis[to]=dis[u]+1,M.push(to);
}
}
return dis[T];
}
ll dinic_dfs(int x,ll lim)
{
if(x==T)return lim;
ll ret=0;
for(int i=cur[x];i;i=edge[i].nxt)
{
cur[x]=i;
int to=edge[i].to;
if(edge[i].val&&dis[to]==dis[x]+1)
{
ll temp=dinic_dfs(to,min(lim,edge[i].val));
if(temp)
{
ret+=temp,lim-=temp;
edge[i].val-=temp,edge[ide(i)].val+=temp;
if(!lim)break;
}
}
}
return ret;
}
ll dinic()
{
ll ans=0;
while(dinic_bfs())ans+=dinic_dfs(S,INF);
return ans;
}
void max_flow()
{
printf("%lld\n",dinic());
}
bool EK_spfa()
{
memset(pre,-1,sizeof(pre));
memset(f,0,sizeof(f));
memset(dis,0x3f,sizeof(dis));
dis[S]=0,lim[S]=INF,used[S]=1;
queue <int> M;
M.push(S);
while(!M.empty())
{
int u=M.front();
M.pop();
for(int i=head[u];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(edge[i].val&&dis[to]>dis[u]+edge[i].pri)
{
dis[to]=dis[u]+edge[i].pri;
pre[to]=i,f[to]=u,lim[to]=min(lim[u],edge[i].val);
if(!used[to])used[to]=1,M.push(to);
}
}
used[u]=0;
}
return pre[T]!=-1;
}
void EK()
{
ll maxf=0,minv=0;
while(EK_spfa())
{
maxf+=lim[T],minv+=dis[T]*lim[T];
int temp=T;
while(temp!=S)edge[pre[temp]].val-=lim[T],edge[ide(pre[temp])].val+=lim[T],temp=f[temp];
}
printf("%lld %lld\n",maxf,minv);
}
void min_cost_max_flow()
{
S=1,T=n;
for(int i=1;i<=m;i++)
{
int x,y;ll z,w;
read(x),read(y),read(z),read(w);
cost_dadd(x,y,z,w);
}
EK();
}
void two_SAT()
{
for(int i=1;i<=m;i++)
{
int x,y,z,w;
read(x),read(y),read(z),read(w);
if(y==1&&w==1)add(x+n,z,0),add(z+n,x,0);
else if(y==1)add(x+n,z+n,0),add(z,x,0);
else if(w==1)add(x,z,0),add(z+n,x+n,0);
else add(x,z+n,0),add(z,x+n,0);
}
n<<=1;
for(int i=1;i<=n;i++)if(!dfn[i])di_tarjan(i);
n>>=1;
for(int i=1;i<=n;i++)if(posi[i]==posi[i+n]){printf("IMPOSSIBLE\n");exit(0);}
printf("POSSIBLE\n");
for(int i=1;i<=n;i++)
{
if(posi[i]<posi[i+n])printf("1 ");
else printf("0 ");
}
printf("\n");
}
bool dfs(int x)
{
for(int i=head[x];i;i=edge[i].nxt)
{
int to=edge[i].to;
if(used[to])continue;
used[to]=1;
if(!f[to]||dfs(f[to])){f[to]=x;return 1;}
}
return 0;
}
int hungary()
{
int ret=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n+m;j++)used[j]=0;
if(dfs(i))ret++;
}
return ret;
}
void two_match()
{
read(n),read(m),read(S);
for(int i=1;i<=S;i++)
{
int x,y;
read(x),read(y);
if(x>n||y>m)continue;
add(x,y+n,0),add(y+n,x,0);
}
printf("%d\n",hungary());
}
int main()
{
two_match();
return 0;
read(n),read(m);//,read(S),read(T);
init();
for(int i=1;i<=m;i++)
{
int x,y;ll z;
read(x),read(y),read(z);
dadd(x,y,z);//,add(y,x,z);
e[i].l=x,e[i].r=y,e[i].v=z;
}
return 0;
}
NOI模板复习组——图论部分的更多相关文章
- wawawa8的模板复习计划
wawawa8的模板复习计划 数据结构 //手写堆 [link][https://www.luogu.org/problemnew/show/P3378] //并查集 [link][https://w ...
- NOIP前的模板复习和注意事项
联赛除去今天刚好只有一个星期了,最后一个星期也很关键,要吃好睡好保持心情愉悦.当然也免不了最后的复习计划. 首先是模板,之前还有很多模板没有复习到,这些东西是一定要落实到位的. 每天往后面写一点... ...
- 模板复习【updating】
马上就要noi了……可能滚粗已经稳了……但是还是要复习模板啊 LCT: bzoj2049 1A 7min # include <stdio.h> # include <string. ...
- NOIP专题复习3 图论-强连通分量
目录 一.知识概述 二.典型例题 1.[HAOI2006]受欢迎的牛 2.校园网络[[USACO]Network of Schools加强版] 三.算法分析 (一)Tarjan算法 (二)解决问题 四 ...
- NOIP专题复习2 图论-生成树
目录 一.知识概述 二.典型例题 1.口袋的天空 三.算法分析 (一)Prim算法 (二)Kruskal 四.算法应用 1.[NOIP2013]货车运输 五.算法拓展 1977: [BeiJing20 ...
- NOIP专题复习1 图论-最短路
一.知识概述 今天我们要复习的内容是图论中的最短路算法,我们在这里讲3种最短路求法,分别是:floyd,dijkstra,spfa. 那么我们从几道例题来切入今天讲解的算法. 二.典型例题 1.热浪 ...
- noip模板复习
自己敲模板还是有很多容易错的地方 写在注释里面了 LCA #include<bits/stdc++.h> #define REP(i, a, b) for(register int i = ...
- NOI ONLINE 入门组 魔法 矩阵快速幂
做了这道题我才发现NOI入门组!=NOIP普及组 题目链接 https://www.luogu.com.cn/problem/P6190 题意 给出一张有向图,你有K次机会可以反转一条边的边权,即让它 ...
- CSP-S 赛前模板复习
快读模板 这个连算法都算不上... inline int read() { int x=0,f=1; char ch=getchar(); while(ch<'0' || ch>'9') ...
- NOI Online 提高组 题解
来补坑了-- 个人认为三道题难度差不多-- 还有要说一嘴,为啥我在其他网站代码都好好的,复制到 cnblogs 上 Tab 就成 8 空格了?不过也懒得改了. T1 序列 首先,遇到这种加一减一还带附 ...
随机推荐
- DOS命令操作
打开CMD的方式 1.开始+系统+命令提示符 2.Win键+R 输入CMD打开控制台(推荐使用) 3.在任意的文件夹下面,按住shift+鼠标右键点击,在此处打开命令行窗口 4.资源管理器的地址栏前面 ...
- docker+react+nginx部署
一.准备工作 1.先确保项目可以正常运行. 2.如果拉代码到Linux下进行打包,注意node版本,我就是版本不同,yarn build一直不成功. 3.找一个nginx的配置文件nginx.conf ...
- 模拟ATM系统 —— 用户存款、取款、转账、修改密码和销户功能
接着上一篇: 5.用户存款功能 分析: *存款就是拿到当前账户对象 *然后让用户输入存款的金额 *调用账户对象的setMoney方法将账户余额修改成存钱后的余额 *存款后需要查询当前账户信息,确认是否 ...
- Arch安装记录(BIOS+GPT)
尝试了下arch安装,并且尝试了下不长用的BIOS + GPT组合.都说arch的wiki强,确实很强,可惜自己的水平看不了多少. https://wiki.archlinux.org/index.p ...
- unity Android路径的相关部分代码
using System; using System.Collections; using System.Collections.Generic; using System.IO; using Uni ...
- 常用IBatis属性
<?xml version="1.0" encoding="utf-8" ?> <sqlMap namespace="GoodDet ...
- git的基本操作(一)
pwd: 显示当前所在的目录路径 ls: 列出当前目录的所有文件 touch: 新建一个文件 rm:删除一个文件 mkdir:新建一个目录 rm -r:删除一个目录 mv:移动一个文件到另一个文件中 ...
- android 打包任务在gradle中
//打包任务task makexxxxxxJar(type: Jar) { //指定生成的jar名 baseName xxxxxx //从哪里打包class文件 from('build/interme ...
- Solution Set - 杭电多校 2022 Day2 一句话题解
A:看了题就很容易想到虚树吧,建出虚树后考虑整体扫一遍虚树,注意到这是一棵根向树,那么统计其实十分简单,将对 \(C\) 类节点的标记下放,\(A,B\) 类节点同时上传,如果在 DFS 的过程中发现 ...
- ABAP 报表的两种下钻功能
在报表开发中往往会由需求要求跳转,SAP中提供了一些下钻的方式. 这里主要介绍两种 submit 和 call transaction submit 引用的是报表名称,以自开发报表居多 call tr ...