整理模板
带权lca+最短路
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162
| #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<cmath> #include<map> #include<stack> #include<set> #include<bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; #define pb(x) push_back(x) #define cls(x, val) memset(x, val, sizeof(x)) #define fi first #define se second #define mp(x, y) make_pair(x, y) #define inc(i, l, r) for(int i=l; i<=r; i++) const ll inf = 0x3f3f3f3f3f3f3f3f; const int maxn = 1e5+10; int readint() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int readll() { ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } struct Node{ int v, next; ll w; }node[maxn<<1]; int tot, head[maxn]; bool vis[maxn]; bool bian[maxn<<1]; bool res[maxn]; ll dis[maxn]; ll diss[50][maxn]; int index; ll g[maxn][20]; int f[maxn][20]; void init(){ tot = 0, cls(head, -1); } int n, m; void add_edge(int u, int v, ll w){ node[tot].v=v, node[tot].w=w, node[tot].next = head[u], head[u] = tot++; } void dfs1(int u){ vis[u] = true; for(int i=head[u]; ~i;i=node[i].next){ int v = node[i].v; if(vis[v]) continue; bian[i] = bian[i^1] = true; dfs1(v); } } struct Qnode{ int u; ll w; Qnode(int _u, ll _w):u(_u), w(_w){} bool operator < (const Qnode & b) const { return w>b.w; } }; void dij(int s, int index){ priority_queue<Qnode> pq; while(!pq.empty()) pq.pop(); for(int i=0; i<=n; i++) dis[i] = inf; dis[s] = 0; cls(vis, 0); pq.push(Qnode(s, 0)); while(!pq.empty()){ Qnode temp = pq.top(); pq.pop(); int u = temp.u; if(vis[u]) continue; vis[u] = true; for(int i=head[u]; ~i; i=node[i].next){ int v = node[i].v; ll w = node[i].w; if(dis[v]>dis[u]+w){ dis[v] = dis[u]+w; if(!vis[v]) pq.push(Qnode(v, dis[v])); } } } for(int i=1; i<=n; i++) { diss[index][i] = dis[i]; } } int d[maxn]; void dfs2(int x){ for(int i=1; i<=17; i++) g[x][i]=g[x][i-1]+g[f[x][i-1]][i-1],f[x][i]=f[f[x][i-1]][i-1]; int v; for(int i=head[x]; ~i; i=node[i].next) if (bian[i] && (v=node[i].v)!=f[x][0]) f[v][0]=x,g[v][0]=node[i].w,d[v]=d[x]+1,dfs2(v); } ll lca(int u, int v){ ll res = 0; if(d[u]<d[v]) swap(u, v); for(int i=17; i>=0; i--){ if(d[f[u][i]]>=d[v]){ res += g[u][i]; u=f[u][i]; } } if(u == v) return res; for(int i=17; i>=0; i--){ if(f[u][i]!=f[v][i]){ res += (g[u][i]+g[v][i]); u=f[u][i], v=f[v][i]; } } return res+g[u][0]+g[v][0]; } int main() { init(); n=readint(), m=readint(); int u, v; ll w; for(int i=1; i<=m; i++){ u=readint(), v=readint(), w=readll(); add_edge(u, v, w), add_edge(v, u, w); } dfs1(1); for(int i=0; i<tot; i++){ if(!bian[i]&&!res[node[i].v]){ res[node[i].v] = true; dij(node[i].v, index++); } } d[1] = 1; dfs2(1); int q; scanf("%d", &q); while(q--){ u=readint(), v=readint(); ll res=lca(u,v); for(int i=0; i<index; i++) res=min(res,diss[i][u]+diss[i][v]); printf("%lld\n", res); } return 0; }
|
图的染色问题
将一个图染色,使得相邻的节点的颜色都不相同,问最少用几种颜色
输入:
n个点m条边
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<cmath> #include<map> #include<stack> #include<set> #include<bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; #define pb(x) push_back(x) #define cls(x, val) memset(x, val, sizeof(x)) #define fi first #define se second #define mp(x, y) make_pair(x, y) #define inc(i, l, r) for(int i=l; i<=r; i++) const int inf = 0x3f3f3f3f; const int maxn = 1e5+10; const int maxm = 2e6+10; int readint() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n, m; struct Node{ int v, w, next; }node[maxm]; int tot, head[maxn]; void add_edge(int u, int v){ node[tot].v=v, node[tot].next=head[u], head[u]=tot++; } int flag[maxn]; int pt[maxn]; int size[maxn]; int color[maxn]; int main() { tot = 0, cls(head, -1); scanf("%d%d", &n, &m); int u, v; for(int i=1; i<=m; i++){ scanf("%d%d", &u, &v); add_edge(u, v), add_edge(v, u); } for (int i=n;i>=1;--i){ int cur=0; for (int j=1;j<=n;++j) if (!flag[j]&&size[j]>=size[cur]) cur=j; flag[cur]=1; pt[i]=cur; for (int j=head[cur];~j;j=node[j].next) size[node[j].v]++; } memset(flag,0,sizeof(flag)); int ans = 0; for (int i=n;i>=1;--i){ for (int j=head[pt[i]];~j;j=node[j].next) flag[color[node[j].v]]=i; color[pt[i]]=1; while (flag[color[pt[i]]]==i) color[pt[i]]++; ans=max(ans,color[pt[i]]); } printf("%d\n",ans); return 0; }
|
BM模板
bm线性递推模板测试
放入的项一般>=8项
这道题目a[i]开放之后满足线性特征,所以可以这样的写
大力猜开根号的式子满足线性递推的关系
update: 事实上网上的题解找规律退推出来的公式确实满足线性递推的关系
模板说明:
只要给出前面的几项,算法就能自动的调整需要的项数,然后进行快速幂运算
模数必须是质数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125
| #include <cstdio> #include <cstring> #include <cmath> #include <algorithm> #include <vector> #include <string> #include <map> #include <set> #include <cassert> using namespace std; #define rep(i,a,n) for (int i=a;i<n;i++) #define per(i,a,n) for (int i=n-1;i>=a;i--) #define pb push_back #define mp make_pair #define all(x) (x).begin(),(x).end() #define fi first #define se second #define SZ(x) ((int)(x).size()) typedef vector<int> VI; typedef long long ll; typedef pair<int,int> PII; const ll mod=1000000007; ll powmod(ll a,ll b) { ll res=1; a%=mod; assert(b>=0); for(; b; b>>=1) { if(b&1)res=res*a%mod; a=a*a%mod; } return res; } int t; ll n; namespace linear_seq { const int N=10010; ll res[N],base[N],_c[N],_md[N]; vector<int> Md; void mul(ll *a,ll *b,int k) { rep(i,0,k+k) _c[i]=0; rep(i,0,k) if (a[i]) rep(j,0,k) _c[i+j]=(_c[i+j]+a[i]*b[j])%mod; for (int i=k+k-1; i>=k; i--) if (_c[i]) rep(j,0,SZ(Md)) _c[i-k+Md[j]]=(_c[i-k+Md[j]]-_c[i]*_md[Md[j]])%mod; rep(i,0,k) a[i]=_c[i]; } ll solve(ll n,VI a,VI b) { ll ans=0,pnt=0; int k=SZ(a); assert(SZ(a)==SZ(b)); rep(i,0,k) _md[k-1-i]=-a[i]; _md[k]=1; Md.clear(); rep(i,0,k) if (_md[i]!=0) Md.push_back(i); rep(i,0,k) res[i]=base[i]=0; res[0]=1; while ((1ll<<pnt)<=n) pnt++; for (int p=pnt; p>=0; p--) { mul(res,res,k); if ((n>>p)&1) { for(int i=k-1; i>=0; i--) res[i+1]=res[i]; res[0]=0; rep(j,0,SZ(Md)) res[Md[j]]=(res[Md[j]]-res[k]*_md[Md[j]])%mod; } } rep(i,0,k) ans=(ans+res[i]*b[i])%mod; if (ans<0) ans+=mod; return ans; } VI BM(VI s) { VI C(1,1),B(1,1); int L=0,m=1,b=1; rep(n,0,SZ(s)) { ll d=0; rep(i,0,L+1) d=(d+(ll)C[i]*s[n-i])%mod; if (d==0) ++m; else if (2*L<=n) { VI T=C; ll c=mod-d*powmod(b,mod-2)%mod; while (SZ(C)<SZ(B)+m) C.pb(0); rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod; L=n+1-L; B=T; b=d; m=1; } else { ll c=mod-d*powmod(b,mod-2)%mod; while (SZ(C)<SZ(B)+m) C.pb(0); rep(i,0,SZ(B)) C[i+m]=(C[i+m]+c*B[i])%mod; ++m; } } return C; } ll gao(VI a,ll n) { VI c=BM(a); c.erase(c.begin()); rep(i,0,SZ(c)) c[i]=(mod-c[i])%mod; return solve(n,c,VI(a.begin(),a.begin()+SZ(c))); } }; int main() { int _; scanf("%d", &_); while(_--) { scanf("%lld",&n); printf("%lld\n", linear_seq::gao(VI{31, 197, 1255, 7997, 50959, 324725, 2069239, 13185773, 84023455, 535421093, 411853810},n-2)); } }
|
敌对搜索
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91
| #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<cmath> #include<map> #include<stack> #include<set> #include<bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; #define pb(x) push_back(x) #define cls(x, val) memset(x, val, sizeof(x)) #define fi first #define se second #define mp(x, y) make_pair(x, y) #define inc(i, l, r) for(int i=l; i<=r; i++) const int inf = 0x3f3f3f3f; const int maxn = 1e3+10; int readint() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n, m, k, l; int a[maxn], b[maxn], c[maxn]; int dp[1005][200+10]; const int TH = 100; int dfs(int p, int now){ if(p == n){ if(now>=k) return 4; if(now<=l) return 1; return 2; } if(dp[p][now+TH]) return dp[p][now+TH]; int &ans = dp[p][now+TH]; int want, hate; if(p&1){ want = 1, hate = 4; } else want = 4, hate = 1; bool flag = false; if(a[p]) { int ret= dfs(p+1, min(now+a[p], TH)); if(ret==want) return ans = want; if(ret!=hate) flag = true; } if(b[p]) { int ret = dfs(p+1, max(now-b[p], -TH)); if(ret==want) return ans = want; if(ret!=hate) flag = true; } if(c[p]) { int ret= dfs(p+1, -now); if(ret==want) return ans = want; if(ret!=hate) flag = true; } if(flag) return ans = 2; else return ans = hate; } int main() { scanf("%d%d%d%d", &n, &m, &k, &l); for(int i=0; i<n; i++) scanf("%d%d%d", &a[i], &b[i], &c[i]); int res = dfs(0, m); if(res == 4){ printf("Good Ending\n"); } else if(res == 1) printf("Bad Ending\n"); else printf("Normal Ending\n"); return 0; }
|
保存最长链上面的所有的节点
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
| #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<cmath> #include<map> #include<stack> #include<set> #include<bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; #define ls (rt<<1) #define rs (rt<<1|1) #define mid (l+r>>1) #define pb(x) push_back(x) #define cls(x, val) memset(x, val, sizeof(x)) #define fi first #define se second #define mp(x, y) make_pair(x, y) #define lowbit(x) (x&(-x)) #define inc(i, l, r) for(int i=l; i<=r; i++) #define dec(i, r, l) for(int i=r; i>=l; i--) const int inf = 0x3f3f3f3f; const int maxn = 2e5+10; const int maxm = 2e5+10; const double pi = acos(-1.0); const double eps = 1e-7; const int mod = 1e9+7; int readint() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } ll readll(){ ll x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n, m; struct Node{ int v, next; ll w; }node[maxm<<1]; int tot, head[maxn]; ll dis[maxn]; int fa[maxn]; bool vis[maxn]; int d[maxn]; int rt; void init(){ tot=0,cls(head, -1); cls(vis, 0); cls(dis, 0); rt=0; } void add_edge(int u, int v, ll w){ node[tot].v=v,node[tot].w=w,node[tot].next=head[u],head[u]=tot++; } void dfs(int u, int p){ fa[u]=p; d[u]=d[p]+1; for(int i=head[u];~i;i=node[i].next){ int v=node[i].v; int w=node[i].w; if(p==v) continue; dis[v]=dis[u]+w; dfs(v, u); } if(dis[u]>dis[rt]) rt=u; } int top=0; int chain[maxn]; ll len2; int rt1, rt2; void getchain(){ int x=rt2; cls(vis, 0); while(x!=fa[rt1]){ chain[top++]=x; vis[x]=true; x=fa[x]; } } ll dis1[maxn]; int dfs1(int u, int fa){ vis[u]=true; for(int i=head[u];~i;i=node[i].next){ int v=node[i].v; ll w=node[i].w; if(vis[v]||v==fa) continue; dis1[v]=dis1[u]+w; dfs1(v, u); } if(dis1[u]>len2) len2=dis1[u]; } int main() { n=readint(); int u, v, w; init(); inc(i, 1, n-1){ u=readint(), v=readint(), w=readll(); add_edge(u, v, w), add_edge(v, u, w); } dfs(1, 0), rt1=rt; cls(dis, 0), cls(d, 0); dfs(rt, 0); rt2=rt; ll len=dis[rt]; getchain(); ll ans = 0; len2=0; int chang = d[rt2]-1; int l=rt2, r=rt1; for(int i=0; i<top; i++){ int id=chain[i]; len2=0, dis1[id]=0; dfs1(id, 0); if(len2 == dis[rt2]-dis[id]) l=id; if(len2 == dis[id]){r=id;break;} } printf("%lld\n%d\n",dis[rt2], d[l]-d[r]); return 0; }
|
最长链的变形
题目大意:
给一个树形的结构,然后选择两条链, 使得一条链的两端不能在另外一条链上,并且满足下列的条件:
公共的点的数量最大
在满足1的条件下,使得两个链的长度最长。
实质上就是求满足条件的点的最长链,
满足条件的链就是子树的度数>=2,否则不能成为公共点
注意结构体的两个最优解的条件比较函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90
| #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<cmath> #include<map> #include<stack> #include<set> #include<bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; #define pb(x) push_back(x) #define cls(x, val) memset(x, val, sizeof(x)) #define fi first #define se second #define mp(x, y) make_pair(x, y) #define inc(i, l, r) for(int i=l; i<=r; i++) const int inf = 0x3f3f3f3f; const int maxn = 2e5+10; pii fir[maxn], sec[maxn]; int readint() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n, m; struct Node{ int id, depth, tot; Node(int _id, int _depth, int _tot):id(_id), depth(_depth), tot(_tot){} Node(){} bool operator < (const Node &b) const{ if(depth == b.depth) return tot<b.tot; else return depth<b.depth; } }; vector<int> G[maxn]; Node best; void dfs(int u, int fa, int dep){ int deg = 0; for(int i=0; i<G[u].size(); i++){ int v = G[u][i]; if(G[u][i] == fa) continue; deg++; dfs(v, u, dep+1); if(fir[v].fi>fir[u].fi){ swap(fir[u], sec[u]); fir[u] = fir[v]; } else if(fir[v].fi>sec[u].fi){ sec[u] = fir[v]; } } if(deg>=2) best = max(best, Node(u, dep, fir[u].fi+sec[u].fi)); if(deg == 0){ fir[u] = make_pair(dep, u); } } int main() { ios::sync_with_stdio(false); cin>>n; int u, v; for(int i=1; i<=n-1; i++){ cin>>u>>v; G[u].push_back(v), G[v].push_back(u); } best = Node(0, 0, 0); dfs(1, 0, 1); int p = best.id; int u1, v1, u2, v2; u1 = fir[p].se, v2 = sec[p].se; cls(fir, 0), cls(sec, 0); best = Node(0, 0, 0); dfs(p, 0, 1); p = best.id; cout<<u1<<" "<<fir[p].se<<endl; cout<<sec[p].se<<" "<<v2<<endl; return 0; }
|
浮点数版本的最小费用流
注意用了float快很多
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
| #include <cstdio> #include <algorithm> #include <cstring> #include <vector> #include <queue> #include <cmath> #include <iostream> #define double float using namespace std; const int maxn = 200+10; namespace mincostflow { const int INF=0x3f3f3f3f; struct node { int to; int cap; double cost; int rev; node(int t=0,int c=0,double _c=0,int n=0): to(t),cap(c),cost(_c),rev(n) {}; }; vector<node> edge[maxn]; void addedge(int from,int to,int cap,double cost) { edge[from].push_back(node(to,cap,cost,edge[to].size())); edge[to].push_back(node(from,0,-cost,edge[from].size()-1)); } double dis[maxn]; bool mark[maxn]; void spfa(int s,int t,int n) { for(int i=0; i<=n+2; i++) dis[i] = double (INF); memset(mark+1,0,n*sizeof(bool)); static int Q[maxn],ST,ED; dis[s]=0; ST=ED=0; Q[ED++]=s; while (ST!=ED) { int v=Q[ST]; mark[v]=0; if ((++ST)==maxn) ST=0; for (node &e:edge[v]) { if (e.cap>0&&dis[e.to]>dis[v]+e.cost) { dis[e.to]=dis[v]+e.cost; if (!mark[e.to]) { if (ST==ED||dis[Q[ST]]<=dis[e.to]) { Q[ED]=e.to,mark[e.to]=1; if ((++ED)==maxn) ED=0; } else { if ((--ST)<0) ST+=maxn; Q[ST]=e.to,mark[e.to]=1; } } } } } } int cur[maxn]; int dfs(int x,int t,int flow) { if (x==t||!flow) return flow; int ret=0; mark[x]=1; for (int &i=cur[x];i<(int)edge[x].size();i++) { node &e=edge[x][i]; if (!mark[e.to]&&e.cap) { if (dis[x]+e.cost==dis[e.to]) { int f=dfs(e.to,t,min(flow,e.cap)); e.cap-=f; edge[e.to][e.rev].cap+=f; ret+=f; flow-=f; if (flow==0) break; } } } mark[x]=0; return ret; } pair<int,double> min_costflow(int s,int t,int n) { int ret=0; double ans=0; int flow = INF; while (flow) { spfa(s,t,n); if (dis[t]==double(INF)) break; memset(cur+1,0,n*sizeof(int)); double len=dis[t]; int f; while ((f=dfs(s,t,flow))>0) ret+=f,ans+=len*f,flow-=f; } return make_pair(ret,ans); } void init(int n) { int i; for (int i = 1; i <= n; i++) edge[i].clear(); } } int n, m; using namespace mincostflow; int ss, tt; double e = 2.718281828459045; int main(int argc, char const *argv[]) { int _; scanf("%d", &_); while(_--){ scanf("%d %d", &n, &m); init(n+2); int x, y, z; double s; ss=1, tt = n+2; for(int i=1; i<=n; i++) { scanf("%d%d", &x, &y); if(x) addedge(ss, i + 1, x, 0); if(y) addedge(i + 1, tt, y, 0); } for (int i = 1; i <= m; i++) { scanf("%d %d %d %f", &x, &y, &z, &s); if(z)addedge(x + 1, y + 1, z-1, -log(1.0 - s)), addedge(x + 1, y + 1, 1, 0.0); } pair<int,double > ans = min_costflow(ss, tt, n+2); printf("%.2f\n", 1.0-pow(e, -ans.second)); } return 0; }
|
线段树维护lca
给定一个树形的结构,每一个询问都是一个区间,然后你可以删除区间里面的一个点,使得他们的lca最大
可以看tutorial,主要的思想就是线段树维护区间的lca和支配这个区间的两个点,这两个点的lca构成区间的lca.
然后找到这两个点之后,就能求两遍答案,之后取最优解就可以了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<cmath> #include<map> #include<stack> #include<set> #include<bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; #define pb(x) push_back(x) #define cls(x, val) memset(x, val, sizeof(x)) #define mp(x, y) make_pair(x, y) #define inc(i, l, r) for(int i=l; i<=r; i++) const int inf = 0x3f3f3f3f; const int maxn = 1e5+10; int readint() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n, m, q; struct Node{ int fa, fi, se; Node(int _fa, int _fi, int _se):fa(_fa), fi(_fi), se(_se){} Node(){} }node[maxn<<2]; int dep[maxn]; int fa[maxn][20]; vector<int> p[maxn]; void dfs(int u, int ff){ for(int i=0; i<p[u].size(); i++){ int v = p[u][i]; if(v == ff) continue; dep[v] = dep[u]+1; fa[v][0] = u; dfs(v, u); } } int lca(int u, int v){ if(dep[u]<dep[v])swap(u, v); for(int i=18; i>=0; i--){ if(dep[fa[u][i]]>=dep[v]){ u=fa[u][i]; } } if(u == v) return u; for(int i=18; i>=0; i--){ if(fa[u][i] != fa[v][i]) u=fa[u][i], v=fa[v][i]; } return fa[u][0]; } Node merge(Node a, Node b){ if(a.fa == -1) return b; if(b.fa == -1) return a; int ff = lca(a.fa, b.fa); if(a.fa == ff) return a; if(b.fa == ff) return b; return Node(ff, a.fi, b.fi); } void build(int rt, int l, int r){ if(l == r) { node[rt] = Node(l, l, l); return ; } else{ int mid = (l+r)>>1; build(rt<<1, l, mid); build(rt<<1|1, mid+1, r); node[rt] = merge(node[rt<<1], node[rt<<1|1]); } } Node query(int rt, int l, int r, int ql, int qr){ if(qr<l||ql>r||l>r) { return Node(-1, -1, -1); } if(ql<=l && qr>=r) { return node[rt]; } int mid = (l+r)>>1; return merge(query(rt<<1, l, mid, ql, qr), query(rt<<1|1, mid+1, r, ql, qr)); } int get(int l, int r, int i){ return merge(query(1, 1, n, l, i-1), query(1, 1, n, i+1, r)).fa; } int main() { scanf("%d%d", &n, &q); int u, v; for(int i=1; i<=n-1; i++){ scanf("%d", &u); p[u].push_back(i+1); } dep[1] = 1, fa[1][0]=1; dfs(1, -1); for(int i=1; i<=18; i++){ for(u=1; u<=n; u++){ fa[u][i] = fa[fa[u][i-1]][i-1]; } } build(1, 1, n); Node temp; int l, r; while(q--){ scanf("%d%d", &l, &r); temp = query(1, 1, n, l, r); u = get(l, r, temp.fi), v = get(l, r, temp.se); if(dep[u]>dep[v]){ printf("%d %d\n", temp.fi, dep[u]-1); } else printf("%d %d\n", temp.se, dep[v]-1); } return 0; }
|
注意事项
__builtin_popcount不能统计long long 类型的1的个数
那种bfs搜索的时候一定要注意是否有无限的状态,否则要用优先队列来维护
unordered_map来代替map或者set
二分的第二种形式 <=x中最大的一个数
1 2 3 4 5
| while(l<r){ int mid = (l+r+1)/2; if(a[mid] <= x) l=mid; else r=mid-1; }
|
整数与浮点数
注意浮点数和整数运算的时候,注意规范。。。
被坑。。。没取floor就Wa了。。。
n/i不是向下取整的意思?
multiset 查找删除
1 2 3
| multiset<int>::iterator it = s.find(*s.begin()); s.erase(it); s.insert(a[i]);
|
切比雪夫距离与欧拉距离的相互转化
将一个点(x,y)的坐标变为(x+y,x−y)后,原坐标系中的曼哈顿距离 = 新坐标系中的切比雪夫距离
将一个点(x,y)的坐标变为(x+y2,x−y2) 后,原坐标系中的切比雪夫距离 = 新坐标系中的曼哈顿距离
例题
找一个点,使得所有点到该点的切比雪夫距离综合最小
切比雪夫距离转化为欧式距离。欧式距离进行排序进行前缀优化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
| #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<queue> #include<cmath> #include<map> #include<stack> #include<set> #include<bitset> using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> pii; #define pb(x) push_back(x) #define cls(x, val) memset(x, val, sizeof(x)) #define fi first #define se second #define mp(x, y) make_pair(x, y) #define inc(i, l, r) for(int i=l; i<=r; i++) const int inf = 0x3f3f3f3f; const int maxn = 1e5+10; int readint() { int x=0,f=1;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} return x*f; } int n, m; struct Node{ ll x, y; }node[maxn]; ll prex[maxn], suffx[maxn]; ll prey[maxn], suffy[maxn]; ll xx[maxn], yy[maxn]; int main() { ios::sync_with_stdio(false); cin>>n; int x, y; ll u, v; for(int i=1; i<=n; i++) { cin>>xx[i]>>yy[i]; xx[i]*=10, yy[i] *= 10; u=(xx[i]+yy[i])/2, v=(xx[i]-yy[i])/2; xx[i] = u, yy[i] = v; node[i].x=u, node[i].y=v; } sort(xx+1, xx+1+n), sort(yy+1, yy+1+n); for(int i=1; i<=n; i++) prex[i] = prex[i-1]+xx[i], prey[i] = prey[i-1]+yy[i]; for(int i=n; i>=1; i--) suffx[i] = suffx[i+1]+xx[i], suffy[i] = suffy[i+1]+yy[i]; ll ans = 1e18; for(int i=1; i<=n; i++){ int idx1 = lower_bound(yy+1, yy+1+n, node[i].y)-yy; ll part1 = idx1*node[i].y-prey[idx1]+suffy[idx1+1]-(n-idx1)*node[i].y; int idx2 = lower_bound(xx+1, xx+1+n, node[i].x)-xx; ll part2 = idx2*node[i].x-prex[idx2]+suffx[idx2+1]-(n-idx2)*node[i].x; ans = min(ans, ll(part1+part2)); } cout<<ans/10<<endl; return 0; }
|
dfs搜索的时候记性记忆化优化
统计砝码能称多种的东西
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| #include <bits/stdc++.h> using namespace std; const int maxn = 2000+10; bool vis[35]; int now = 1; int n, m; int a[35]; bool f[maxn]; int ans = 0; void count(){ memset(f, 0, sizeof(f)); f[0] = true; for(int i=1; i<=n; i++){ if(!vis[i]){ for(int j=2000; j>=a[i]; j--){ if(f[j-a[i]]) f[j] = true; } } } int cnt = 0; for(int i=1; i<=2000; i++) if(f[i]) cnt++; ans = max(ans, cnt); } void dfs(int tot){ if(tot == m){ count(); return; } for(int i=now; i<=n; i++){ if(!vis[i]){ vis[i] = true; now = i+1; dfs(tot+1); vis[i] = false; } } } int main(){ scanf("%d%d", &n, &m); for(int i=1; i<=n; i++) scanf("%d", &a[i]); sort(a+1, a+1+n); dfs(0); printf("%d\n", ans); return 0; }
|
未解决的问题