计算一下能够达到水是多少,能够到达的糖是多少
枚举水,而后加最多能加的糖,是\(min(F - i *100,E * 100)\),计算密度,和前一个比较就行node
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define MAXN 100005 #define eps 1e-12 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int A,B,C,D,E,F; int w[35],t[3005]; void Solve() { read(A);read(B);read(C);read(D);read(E);read(F); w[0] = 1; for(int i = 1 ; i <= F / 100 ; ++i) { if(i >= A) w[i] |= w[i - A]; if(i >= B) w[i] |= w[i - B]; } t[0] = 1; for(int i = 1 ; i <= F ; ++i) { if(i >= C) t[i] |= t[i - C]; if(i >= D) t[i] |= t[i - D]; } t[0] = 0; for(int i = 1 ; i <= F ; ++i) { if(t[i]) t[i] = i; else t[i] = t[i - 1]; } int a = A * 100,b = 0; for(int i = 1 ; i <= F / 100 ; ++i) { if(!w[i]) continue; int rem = min(F - i * 100,i * E); int s = t[rem],p = i * 100 + s; if(s * a > b * p) {a = p;b = s;} } out(a);space;out(b);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
很容易发现边确定都被涵盖在最短路的数值里(若是要构造出一个价值最小的图)c++
咱们从小到大加边,对于一个(u,v)最短路,若是这个最短路不用额外边,那么就是用一个别的点k,(u,k) + (k,v) = (u,v)chrome
若是算出来的最短路小于给定值,那么就不合法spa
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define MAXN 100005 #define eps 1e-12 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int64 A[305][305]; int64 B[305][305],ans; pii p[100005]; int tot,N; void Solve() { read(N); for(int i = 1 ; i <= N ; ++i) { for(int j = 1 ; j <= N ; ++j) { read(A[i][j]); if(i != j) B[i][j] = 1e16; if(i < j) p[++tot] = mp(i,j); } } sort(p + 1,p + tot + 1,[](pii a,pii b){return A[a.fi][a.se] < A[b.fi][b.se];}); for(int i = 1 ; i <= tot ; ++i) { int u = p[i].fi,v = p[i].se; for(int j = 1 ; j <= N ; ++j) { B[u][v] = min(B[u][j] + B[j][v],B[u][v]); } B[v][u] = B[u][v]; if(B[u][v] < A[u][v]) {puts("-1");return;} if(B[u][v] == A[u][v]) continue; ans += A[u][v]; B[u][v] = B[v][u] = A[u][v]; } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
咱们但愿除了和该点同色的值以外,另外一种颜色的值总和尽量的小,这样容易达成目标
能够直接作一个背包dp就行,每次尽可能取最小的值当作另外一种颜色的值rest
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define MAXN 5005 #define eps 1e-12 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N,P[MAXN],X[MAXN]; int dp[MAXN],sum[MAXN]; bool f[MAXN][MAXN]; void Solve() { read(N); for(int i = 2 ; i <= N ; ++i) read(P[i]); for(int i = 1 ; i <= N ; ++i) read(X[i]); for(int i = 1 ; i <= N ; ++i) f[i][0] = 1; for(int i = N ; i >= 1 ; --i) { bool flag = 0; for(int j = X[i] ; j >= 0 ; --j) { if(f[i][j]) { dp[i] = sum[i] - j; flag = 1; break; } } if(!flag) { puts("IMPOSSIBLE");return; } if(P[i]) { for(int j = X[P[i]] ; j >= 0 ; --j) { bool t = 0; if(j >= X[i]) t |= f[P[i]][j - X[i]]; if(j >= dp[i]) t |= f[P[i]][j - dp[i]]; f[P[i]][j] = t; } sum[P[i]] += X[i] + dp[i]; } } puts("POSSIBLE"); } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }
行列拆点,有一个点就行列之间连边code
连出的图确定是不少个基环外向树森林rem
至关于给每一个点分配一个边,给环上的点分配边就两种方式,每种分别计算方案数get
分配完以后每一个点假如横向,这个点往横向以前全部的点连一条边
竖向同理it
而后就是求一个树的dfs序个数class
最后把全部联通块的答案合出来就行
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define mp make_pair #define pb push_back #define space putchar(' ') #define enter putchar('\n') #define MAXN 200005 #define eps 1e-12 //#define ivorysi using namespace std; typedef long long int64; typedef unsigned int u32; typedef double db; template<class T> void read(T &res) { res = 0;T f = 1;char c = getchar(); while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } const int MOD = 1000000007; int inc(int a,int b) { return a + b >= MOD ? a + b - MOD : a + b; } int mul(int a,int b) { return 1LL * a * b % MOD; } int fpow(int x,int c) { int res = 1,t = x; while(c) { if(c & 1) res = mul(res,t); t = mul(t,t); c >>= 1; } return res; } void update(int &x,int y) { x = inc(x,y); } struct node { int to,next; }E[MAXN * 4]; int x[MAXN],y[MAXN],N,fac[MAXN],invfac[MAXN]; map<pii,int> zz; int head[MAXN],sumE; bool vis[MAXN]; int sum,Ncnt,fa[MAXN],s,t,pos[MAXN],par[MAXN]; vector<int> c[MAXN],r[MAXN],rec,cyc; int rpos[MAXN],cpos[MAXN],siz[MAXN]; vector<int> son[MAXN]; void add(int u,int v) { E[++sumE].to = v; E[sumE].next = head[u]; head[u] = sumE; } pii depos(int a,int b) { if(a > b) swap(a,b); b -= N; return mp(a,b); } bool dfs(int u) { ++Ncnt; bool flag = 0; vis[u] = 1; for(int i = head[u] ; i ; i = E[i].next) { ++sum; int v = E[i].to; if(!vis[v]) { fa[v] = u; if(dfs(v)) { flag = 1; pos[zz[depos(u,v)]] = u; } } else if(v != fa[u] && !flag){ s = u,t = v; flag = 1; rec.pb(zz[depos(u,v)]); } } if(!flag && fa[u]) { pos[zz[depos(u,fa[u])]] = u; } if(fa[u]) rec.pb(zz[depos(u,fa[u])]); return flag; } int Calc(int u) { siz[u] = 1; int res = 1; for(auto v : son[u]) { res = mul(res,Calc(v)); res = mul(res,invfac[siz[v]]); siz[u] += siz[v]; } res = mul(res,fac[siz[u] - 1]); return res; } int Process() { int res = 0; for(auto t : rec) par[t] = 0; for(auto t : rec) { if(pos[t] > N) { for(int i = 0 ; i < cpos[t] ; ++i) { par[zz[mp(c[y[t]][i],y[t])]] = t; } } else { for(int i = 0 ; i < rpos[t] ; ++i) { par[zz[mp(x[t],r[x[t]][i])]] = t; } } son[t].clear(); } son[0].clear(); for(auto t : rec) { son[par[t]].pb(t); } return Calc(0); } void Solve() { read(N); for(int i = 1 ; i <= 2 * N ; ++i) { read(x[i]);read(y[i]);add(x[i],y[i] + N);add(y[i] + N,x[i]); zz[mp(x[i],y[i])] = i; r[x[i]].pb(y[i]);c[y[i]].pb(x[i]); } for(int i = 1 ; i <= N ; ++i) { sort(r[i].begin(),r[i].end()); sort(c[i].begin(),c[i].end()); for(int j = 1 ; j < r[i].size() ; ++j) rpos[zz[mp(i,r[i][j])]] = j; for(int j = 1 ; j < c[i].size() ; ++j) cpos[zz[mp(c[i][j],i)]] = j; } fac[0] = 1; for(int i = 1 ; i <= 2 * N ; ++i) fac[i] = mul(fac[i - 1],i); invfac[2 * N] = fpow(fac[2 * N],MOD - 2); for(int i = 2 * N - 1 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1); int ans = fac[2 * N]; for(int i = 1 ; i <= 2 * N ; ++i) { if(!vis[i]) { sum = 0;Ncnt = 0; rec.clear(); dfs(i); ans = mul(ans,invfac[Ncnt]); if(Ncnt * 2 != sum) {puts("0");return;} int p = s; cyc.clear(); while(1) { cyc.pb(p); if(p == t) break; p = fa[p]; } int tmp = 0; cyc.pb(s); for(int i = 0 ; i < cyc.size() - 1 ; ++i) { pos[zz[depos(cyc[i],cyc[i + 1])]] = cyc[i]; } update(tmp,Process()); for(int i = cyc.size() - 1 ; i >= 1 ; --i) { pos[zz[depos(cyc[i],cyc[i - 1])]] = cyc[i]; } update(tmp,Process()); ans = mul(ans,tmp); } } out(ans);enter; } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Solve(); }