标签:差分约束
Time Limit: 2000MS | Memory Limit: 65536K | |
Total Submissions: 20775 | Accepted: 7859 |
Description
Input
Output
Sample Input
5 3 7 3 8 10 3 6 8 1 1 3 1 10 11 1
Sample Output
6
题意:告诉你n个区间,要在第i区间至少取ci个数,问所有区间总共至少去多少个数?
这题的构图很是巧妙,把每个边界看成节点,Xi表示0-i有多少个数被选上,则每个区间[li,ri]可以推出X[ri]-X[li-1]>=Ci,即:X[li-1]-X[ri]<=-Ci。
潜在不等式:
1、X[i]-X[i+1]<=0;
2、X[i+1]-X[i]<=0.
本题我多了一个离散化操作。
#include <iostream> #include <cstdio> #include <map> #include <queue> #include <cstring> #include <algorithm> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; const int maxn = 2000100; struct edge{ int u , v , d; edge(int a = 0 , int b = 0 , int c = 0){ u = a , v = b , d = c; } }e[maxn]; int head[maxn] , next[maxn] , cnt , n; int dis[maxn] , vis[maxn] , vt[maxn] , index; map<int , int> mp; struct interval{ int l , r , value; interval(int a = 0 , int b = 0 , int c = 0){ l = a , r = b , value = c; } }; vector<interval> I; void add(int u , int v , int d){ e[cnt] = edge(u , v , d); next[cnt] = head[u]; head[u] = cnt++; } void initial(){ I.clear(); for(int i = 0; i < maxn; i++){ head[i] = -1; dis[i] = INF; vis[i] = 0; vt[i] = 0; } cnt = 0; index = 0; mp.clear(); } void readcase(){ int a , b , c; for(int i = 0; i < n; i++){ scanf("%d%d%d" , &a , &b , &c); b++; I.push_back(interval(a , b , c)); mp[a] = 0; mp[b] = 0; } map<int , int>::iterator it; for(it = mp.begin(); it != mp.end(); it++){ it -> second = index++; } it = mp.begin(); for(int i = 0; i < index-1; i++){ int tem = it->first; it++; add(i+1 , i , 0); add(i , i+1 , it->first - tem); } } bool SPFA(int start){ queue<int> q; q.push(start); vt[start]++; while(!q.empty()){ int u = q.front(); vis[u] = 0; if(vt[u]>index) return false; q.pop(); int Next = head[u]; while(Next != -1){ int v = e[Next].v , d = e[Next].d; if(dis[v] > dis[u]+d){ dis[v] = dis[u]+d; if(vis[v] == 0){ vis[v] = 1; vt[v]++; q.push(v); } } Next = next[Next]; } } return true; } void computing(){ for(int i = 0; i < I.size(); i++){ add(mp[I[i].r] , mp[I[i].l] , -1*I[i].value); } dis[index-1] = 0; SPFA(index-1); printf("%d\n" , -1*dis[0]); } int main(){ while(scanf("%d" , &n) != EOF){ initial(); readcase(); computing(); } return 0; }
poj 1201 Intervals(差分约束),布布扣,bubuko.com
标签:差分约束
原文地址:http://blog.csdn.net/u011836218/article/details/31788457