2020/8/29
英语四级一篇
看了下析合树。
补了多校一题费用流+1题网络流题目
晚上打了场atcode
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include"vector" #include<queue> #include"set" #include"map" using namespace std; typedef long long ll; inline int read(){ int s = 0, w = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); } return s * w; } const int inf=1e9; const int N=300,M=N*N+N+7,E=500005; int ver[E], edge[E], Next[E], head[E]; int cost[E],d[M]; int incf[M], pre[M], v[M]; ll ans; int n, k, tot, s, t, maxflow,m,q[E]; vector<int> G; void add(int x, int y, int z, int c) { // 正向边,初始容量z,单位费用c ver[++tot] = y, edge[tot] = z, cost[tot] = c; Next[tot] = head[x], head[x] = tot; // 反向边,初始容量0,单位费用-c,与正向边“成对存储” ver[++tot] = x, edge[tot] = 0, cost[tot] = -c; Next[tot] = head[y], head[y] = tot; } bool spfa() { queue<int> q; for(int i = 0; i <= n + m + m + n; i ++) d[i] = inf; memset(v, 0, sizeof(v)); q.push(s); d[s] = 0; v[s] = 1; // SPFA 求最长路 incf[s] = 1 << 30; // 增广路上各边的最小剩余容量 while (q.size()) { int x = q.front(); v[x] = 0; q.pop(); for (int i = head[x]; i; i = Next[i]) { if (!edge[i]) continue; // 剩余容量为0,不在残量网络中,不遍历 int y = ver[i]; if (d[y]>d[x] + cost[i]) { d[y] = d[x] + cost[i]; incf[y] = min(incf[x], edge[i]); pre[y] = i; // 记录前驱,便于找到最长路的实际方案 if (!v[y]) v[y] = 1, q.push(y); } } } if (d[t] == inf) return false; // 汇点不可达,已求出最大流 return true; } // 更新最长增广路及其反向边的剩余容量 void update() { int x = t; while (x != s) { int i = pre[x]; edge[i] -= incf[t]; edge[i ^ 1] += incf[t]; // 利用“成对存储”的xor 1技巧 x = ver[i ^ 1]; } G.push_back(d[t]); maxflow += incf[t]; ans += d[t] * incf[t]; //printf("%d %d sd\n ",d[t],incf[t]); } int main() { while(~scanf("%d%d",&n,&m)){ tot = 1; memset(head,0,sizeof(head)); G.clear(); memset(cost,0,sizeof(cost)); t = n; s = 1; for(int i = 1; i <= m; i ++) { int a = read(),b = read(),x = read(); add(a,b,1,x); } maxflow = ans = 0; while(spfa()){ update(); //printf("%lld %lld\n",maxflow,ans); } // printf("%lld\n",ans); int q = read(); while(q --){ int u = read(),v = read(); ll ansu = 0,ansv = v; for(int i = 0; i < G.size(); i ++){ if(v > u){ v -= u; ansu += G[i] * (ll)u; } else { ansu += G[i] * (ll)v; v = 0; } } if(v){ puts("NaN"); continue; } ll gcd=__gcd(ansu,ansv); ansu/=gcd,ansv/=gcd; printf("%lld/%lld\n",ansu,ansv); } } } #include"stdio.h" #include"string.h" #include"stack" #include"map" #include"math.h" #include"iostream" #include"vector" #include"queue" #include"algorithm" using namespace std; #define OK printf("\n"); #define Debug printf("this_ok\n"); #define INF 1e18 typedef long long ll; #define scanll(a,b) scanf("%lld%lld",&a,&b); #define scanl(a) scanf("%lld",&a); #define printl(a,b) if(b == 0) printf("%lld ",a); else printf("%lld\n",a); #define print_int(a,b) if(b == 0) printf("%d ",a); else printf("%d\n",a); typedef pair<int,int> PII; inline int read(){ int s = 0, w = 1; char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') w = -1; ch = getchar(); } while(ch >= '0' && ch <= '9') { s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar(); } return s * w; } const ll mod = 998244353; const int N = 50010,M = 300010; const double pi = acos(-1); const int inf = 1 << 29; const int dirx[4] = {-1,0,1,0}; const int diry[4] = {0,1,0,-1}; int n,m,t,s,tot; ll maxflow,sum; int head[N],ver[M],Next[M],edge[M],d[N]; int a[N],dp[N]; queue<int> q; void add(int x,int y,int z){ ver[++ tot] = y; Next[tot] = head[x]; edge[tot] = z; head[x] = tot; ver[++ tot] = x; edge[tot] = 0; Next[tot] = head[y]; head[y] = tot; } bool bfs(){ memset(d,0,sizeof(d)); while(q.size())q.pop(); q.push(s); d[s] = 1; while(q.size()){ int x = q.front(); q.pop(); for(int i = head[x]; i; i = Next[i]) if(edge[i] && !d[ver[i]]){ q.push(ver[i]); d[ver[i]] = d[x] + 1; if(ver[i] == t) return 1; } } return 0; } int dinic(int x,ll flow){ if(x == t) return flow; ll rest = flow,k; for(int i = head[x]; i && rest; i = Next[i]){ if(edge[i] && d[ver[i]] == d[x] + 1){ k = dinic(ver[i],min(rest,(ll)edge[i])); if(!k) d[ver[i]] = 0; edge[i] -= k; edge[i ^ 1] += k; rest -= k; } } return flow - rest; } int main(){ n = read();s = 2 * n + 1; t = s + 1; int maxx = 0; for(int i = 1; i <= n; i ++) a[i] = read(); if(n == 1){ printf("1\n1\n1\n"); return 0; } for(int i = 1; i <= n; i ++){ for(int j = 1; j < i; j ++){ if(a[i] >= a[j] && dp[j] > dp[i]){ dp[i] = dp[j]; } } dp[i] += 1; maxx = max(maxx,dp[i]); } printf("%d\n",maxx); tot = 1; for(int i = 1; i <= n; i ++){ add(i,i + n,1); if(dp[i] == 1) add(s,i,1); if(dp[i] == maxx) add(i + n,t,1); } for(int i = 1; i <= n; i ++) for(int j = i + 1; j <= n; j ++){ if(a[j] >= a[i] && dp[j] == dp[i] + 1){ add(i + n,j,1); } } ll flow = 0; while(bfs()) while(flow = dinic(s,inf)) maxflow += flow; printf("%lld\n",maxflow); tot = 1; memset(head,0,sizeof(head)); for(int i = 1; i <= n; i ++){ add(i,i + n,1); if(dp[i] == 1) add(s,i,1); if(dp[i] == maxx) add(i + n,t,1); } for(int i = 1; i <= n; i ++) for(int j = i + 1; j <= n; j ++){ if(a[j] >= a[i] && dp[j] == dp[i] + 1){ add(i + n,j,1); } } add(1,1 + n,inf); add(s,1,inf); if(dp[n] == maxx){ add(n,n + n,inf); add(n + n,t,inf); } flow = 0; maxflow = 0; while(bfs()) while(flow = dinic(s,inf)) maxflow += flow; printf("%lld\n",maxflow); } /* 3 1 2 3 2 2 6 */