這是我在codeforces上做的第一個網路流的題目,思維還不錯,講講
題意:給你n個任務,k個機器,n個任務的起始時間,期間,完成任務的獲利
每個機器可以完成任何一項任務,但是同一時刻只能完成一項任務,一旦某台機器在完成某項任務時,直到任務結束,這台機器都不能去做其他任務
最後問你當獲利最大時,應該安排那些機器工作,即輸出方案
剛看到題就想到一個貪心的思路,如果一台機器完成了某項工作,它應該繼續去完成接下來最先開始的工作,感覺有點像網路流裡面的建圖啊,於是繼續往這個方向YY,
我擦,結果還真可以網路流來搞。
具體建圖方法:
建立源匯S T‘
對任務按照起始時間s按升序排序
拆點:
u 向 u'連一條邊 容量為 1 費用為 -c,
u' 向 T連一條邊 容量為 inf 費用為 0;
如果任務u完成後接下來最先開始的是任務v
則從u' 向 v連一條邊,容量inf 費用 0.
另外,任務從前往後具有傳遞性,所以必須是第i個任務向第i+1個任務建邊,容量為inf
最後,限制一下起始點向第一個任務的流量即可(即K)
my code
View Code
#include<cstdio>#include<cstring>#include<algorithm>#include<queue>using namespace std;int Sum_Flow;const int N = 3000;const int M = 100000;const int inf = ~0u>>2;struct Edge{ int u,v,cap,cost; int next;}edge[M];int E;int head[N],dist[N],pre[N];bool vis[N];void init(){ E=0; memset(head,-1,sizeof(head));}void add_edge(int u,int v,int cap,int cost){ edge[E].u=u;edge[E].v=v;edge[E].cap=cap;edge[E].cost=cost; edge[E].next=head[u];head[u]=E++; edge[E].u=v;edge[E].v=u;edge[E].cap=0;edge[E].cost=-cost; edge[E].next=head[v];head[v]=E++;}bool spfa(int s,int t,int n){ queue<int> Q; fill(vis,vis+n+1,false); fill(pre,pre+n+1,-1); fill(dist,dist+n+1,inf); vis[s]=true;dist[s]=0; Q.push(s); while(!Q.empty()) { int u=Q.front();Q.pop();vis[u]=false; for(int i=head[u];i!=-1;i=edge[i].next) { int v=edge[i].v; if(edge[i].cap && dist[v] > dist[u]+ edge[i].cost) { dist[v] = dist[u]+edge[i].cost; pre[v]=i; if(!vis[v]) { Q.push(v); vis[v]=true; } } } } if(dist[t] == inf) return false; return true;}int MCMF(int s,int t,int n){ int flow=0; int minflow,mincost=0; while(spfa(s,t,n)) { minflow=inf+1; for(int i=pre[t];i!=-1;i=pre[edge[i].u]) if(edge[i].cap < minflow) minflow=edge[i].cap; flow+=minflow; for(int i=pre[t];i!=-1;i=pre[edge[i].u]) { edge[i].cap-=minflow; edge[i^1].cap+=minflow; } mincost += dist[t] * minflow; } Sum_Flow = flow; return mincost;}struct node{ int s,t,c; int id;}in[N];int ans[N];int cmp(node a, node b){ return a.s<b.s;}int main(){ int n,k; while(scanf("%d%d",&n,&k)!=EOF) { init(); int S = 2*n,T = 2*n+1; for(int i=0;i<n;i++){ scanf("%d%d%d",&in[i].s,&in[i].t,&in[i].c); in[i].t=in[i].s+in[i].t-1; in[i].id=i; } sort(in,in+n,cmp); for(int i=0;i<n;i++) { add_edge(i,i+n,1,-in[i].c); add_edge(i+n,T,inf,0); if(i<n-1) add_edge(i,i+1,inf,0); for(int j=i+1;j<n;j++) { if(in[i].t<in[j].s) { add_edge(i+n,j,inf,0); break; } } } add_edge(S,0,k,0); add_edge(n-1,T,k,0); MCMF(S,T,T+1); memset(ans,0,sizeof(ans)); for(int i=0;i<E;i+=2) { if(!edge[i].cap) { int u=edge[i].u,v=edge[i].v; if(u!=S && u!=T && u<n) { ans[in[u].id]=1; } } } for(int i=0;i<n;i++) printf("%d ",ans[i]); puts(""); } return 0;}