2023/4/12小记
CGUO
link
tag:平面图转对偶图,最短路。
一个引理是平面图最小割是对偶图最短路。
感性理解:最短路经过的边就是割的边,可以证明那个定理是充要的但是没看懂。
#include<bits/stdc++.h>
using namespace std;
const int N=1503;
const int M=N*N;
template<class T>void read(T &x){
x=0;int f=0;char ch=getchar();
while(ch<'0'||ch>'9') {f|=(ch=='-');ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
x=f?-x:x;return;
}
int n,m,S,T;
int cnt,hd[M];
struct node{int to,nxt,val;}a[M<<2];
inline void add(int u,int v,int w){
a[++cnt]=(node){v,hd[u],w};
hd[u]=cnt;
}
int vis[M],dis[M];
int dijkstra(){
memset(dis,0x3f3f3f3f,sizeof(dis));
priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> q;
q.push(make_pair(0,S));
dis[S]=0;
while(!q.empty()){
int u=q.top().second;
q.pop();
if(vis[u])continue;
vis[u]=1;
for(int i=hd[u];i;i=a[i].nxt){
int v=a[i].to;
if(dis[u]+a[i].val<dis[v]){
dis[v]=dis[u]+a[i].val;
q.push(make_pair(dis[v],v));
}
}
}
return dis[T];
}
inline int id(int x,int y){return (x-1)*1500+y;}
int main(){
read(n),read(m);
S=id(1,0),T=id(n,1);
for(int i=1;i<=n;i++)
for(int j=1;j<m;j++){
int tmp;
read(tmp);
if(i==n) add(S,id(i-1,j),tmp);
else if(i==1) add(id(i,j),T,tmp);
else add(id(i,j),id(i-1,j),tmp);
}
for(int i=1;i<n;i++){
for(int j=1,tmp;j<=m;j++){
read(tmp);
if(j==1)add(S,id(i,j),tmp);
else if(j==m)add(id(i,j-1),T,tmp);
else add(id(i,j-1),id(i,j),tmp);
}
}
cout<<dijkstra();
return 0;
}
无源汇有上下界可行流
很抽象啊感觉。就是说决定每个点的出流量和进流量是否守恒,不守恒就强制加一个流量让他守恒,保证下界。
//#pragma GCC optimize(2)
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5,M=1e6+5;
class Dinic{
public :
const int INF=2e10;
inline void add(int u,int v,int w){
AddEdge(u,v,w);
AddEdge(v,u,0);
}
int S,T;
int do_Dinic(){
int ret=0;
while(bfs()){
int tmp;
while(tmp=dfs(S,INF))
ret+=tmp;
}
return ret;
}
void set_ST(int ss,int tt){S=ss,T=tt;}
struct node{int to,val,nxt;}a[M<<1];
int hd[N],cur[N],cntedge;
inline void AddEdge(int u,int v,int w){
a[cntedge]=(node){v,w,hd[u]};
hd[u]=cntedge++;
}
int dis[N];
bool bfs(){
memset(dis,-1,sizeof(dis));
memcpy(cur,hd,sizeof(hd));
queue<int> q;
q.push(S);dis[S]=0;
while(!q.empty()){
int u=q.front();
q.pop();
if(u==T) return true;
for(int i=hd[u];i;i=a[i].nxt){
int to=a[i].to;
if(dis[to]==-1&&a[i].val){
dis[to]=dis[u]+1;
q.push(to);
}
}
}
return dis[T]!=-1;
}
int dfs(int u,int flow){
if(u==T) return flow;
int now=0;
for(int i=cur[u];i&&now<flow;i=a[i].nxt){
cur[u]=i;
int to=a[i].to;
if(dis[to]==dis[u]+1&&a[i].val){
int dlt=dfs(to,min(flow-now,a[i].val));
a[i].val-=dlt,a[i^1].val+=dlt;
now+=dlt;
}
}
return now;
}
private :
}D;
int n,m;
int u[M],v[M],up[M],dw[M],tmp[N];
signed main(){
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin>>n>>m;
D.set_ST(0,n+1);
for(int i=1;i<=m;i++){
cin>>u[i]>>v[i]>>dw[i]>>up[i];
D.add(u[i],v[i],up[i]-dw[i]);
tmp[u[i]]-=dw[i],tmp[v[i]]+=dw[i];
}
int sum=0;
for(int i=1;i<=n;i++) {
if(tmp[i]>=0) D.add(D.S,i,tmp[i]);
else D.add(i,D.T,-tmp[i]),sum-=tmp[i];
}
if(D.do_Dinic()==sum) {
cout<<"YES\n";
for(int i=1;i<=m+m;i+=2) {
cout<<dw[i/2+1]+D.a[i].val<<endl;
}
}
else {
cout<<"NO";
}
return 0;
}
一些趣事
听课的实习老师很多,老师进来之后拿着一本必修二,然后我们在讲选修一()一脸迷茫.jpg
找到老师在讲什么之后 wlf:我们来扩展一下。
然后老师更懵逼了。
笑傻了()