Wannafly summer camp
阿新 • • 發佈:2018-12-12
樣例輸入
3 3
1 2
1 2
1 2
樣例輸出
5
分析:
考慮費用流時把每個part拆成n個點,選擇第i個點的代表為放置i塊蛋糕和(i - 1)塊蛋糕的時間差,這個時間差是遞增的,因此在費用流的過程中必定會從小到大選擇
具體建圖:左邊n個點代表n個蛋糕,右邊m * n個點代表m個part,每個part拆成n個點。源點向每個左邊的點連一條流量1費用0的邊,每個右邊的點向匯點連一條流量1費用0的編。每個蛋糕向可以放的兩個part的所有點連邊,連向第i個點的費用為i^2 - (i - 1)^2,流量為1。這樣求最小費用流既為答案。
#include <cstdio> #include <cstring> #include <vector> #include <queue> using namespace std; const int INF = 0x3f3f3f3f; const int MAXN = 5005; struct Edge{ int value,flow,to,rev; Edge(){} Edge(int a,int b,int c,int d):to(a),value(b),flow(c),rev(d){} }; vector<Edge> E[MAXN]; inline void Add(int from,int to,int flow,int value){ E[from].push_back(Edge(to,value,flow,E[to].size())); E[to].push_back(Edge(from,-value,0,E[from].size()-1)); } bool book[MAXN];//用於SPFA中標記是否在queue中 int cost[MAXN];//存費用的最短路徑 int pre[MAXN];//存前節點 int pree[MAXN];//存在前節點的vector中的下標 bool Spfa(int from,int to){ memset(book,false,sizeof book); memset(cost,INF,sizeof cost); book[from] = true; cost[from] = 0; queue<int> Q; Q.push(from); while(!Q.empty()){ int t = Q.front(); book[t] = false; Q.pop(); for(int i=0 ; i<E[t].size() ; ++i){ Edge& e = E[t][i]; if(e.flow > 0 && cost[e.to] > cost[t] + e.value){ cost[e.to] = cost[t] + e.value; pre[e.to] = t; pree[e.to] = i; if(book[e.to] == false){ Q.push(e.to); book[e.to] = true; } } } } return cost[to] != INF; } int Work(int from,int to){ int sum = 0; while(Spfa(from,to)){ int mflow = INF;//SPFA找到的最短路徑的最小容量 int flag = to; while(flag != from){ mflow = min(mflow,E[pre[flag]][pree[flag]].flow); flag = pre[flag]; } flag = to; while(flag != from){ sum += E[pre[flag]][pree[flag]].value * mflow; E[pre[flag]][pree[flag]].flow -= mflow; E[flag][E[pre[flag]][pree[flag]].rev].flow += mflow; flag = pre[flag]; } } return sum; } int main(){ int N,M; while(scanf("%d %d",&N,&M) == 2){ int a,b; for(int i=1 ; i<=N ; ++i){ scanf("%d %d",&a,&b); Add(i,a+N,1,0); Add(i,b+N,1,0); Add(0,i,1,0); } for(int i=1 ; i<=M ; ++i){ for(int j=1 ; j<=99 ; j+=2){//99 = 2*50-1; Add(i+N,M+N+1,1,j); } } printf("%d\n",Work(0,M+N+1)); for(int i=0 ; i<=M+N+1 ; ++i)E[i].clear(); } return 0; }
樣例輸入
1
1 1 1 1 0 1000000007 10
樣例輸出
904493530
分析:
由於取模的常數為64bit整數,所以考慮使用,然後暴力求解即可
#include<bits/stdc++.h> using namespace std; typedef long long ll; ll ksc(ll x,ll y,ll mod) { return (x*y-(ll)((long double)x/mod*y)*mod+mod)%mod; } ll m0,m1,c,M,k; ll a0,a1; int main() { int T; scanf("%d",&T); while(T--){ scanf("%lld%lld%lld%lld%lld%lld%lld",&a0,&a1,&m0,&m1,&c,&M,&k); ll ans=ksc(a0,a1,M); ll a2; for(int i=2;i<=k;i++) { a2=((ksc(m0,a1,M)+ksc(m1,a0,M))%M+c)%M; ans=ksc(ans,a2,M); a0=a1; a1=a2; } printf("%lld\n",ans); } return 0; }