1. 程式人生 > >洛谷P2294 [HNOI2005]狡猾的商人 ,神奇做法——貪心

洛谷P2294 [HNOI2005]狡猾的商人 ,神奇做法——貪心

mat n) void noi 帶權並查集 新的 include font target

                      HNOI2005狡猾的商人,洛谷鏈接 原題入口

  看到大牛都是寫的差分約束或帶權並查集,本蒟蒻都不太會(還是用差分約束過了的QAQ),但是想出一種貪心的策略,運用神奇的優先隊列實現。思路是:先按左端點為第一排序關鍵字,再排右端點。之後就開始兩兩比較,如果左端點相等,就比較右端點,如果相等,就比較值,如果值不同,就直接輸出false,否則輸出true,如果右端點不等,就把相同的部分抵消掉,把新的區間再壓入優先隊列。直到不能操作,就輸出true。下附代碼:

 1 #include<queue>
 2 #include<cmath>
 3
#include<cstdio> 4 #include<cstring> 5 #include<iostream> 6 #include<algorithm> 7 #define N 1100 8 using namespace std; 9 inline void read(int &x) 10 { 11 x=0; 12 int p=1; 13 char c=getchar(); 14 while(!isdigit(c)){if(c==-)p=-1;c=getchar();} 15 while
(isdigit(c)) {x=(x<<1)+(x<<3)+(c^0);c=getchar();} 16 x*=p; 17 18 }//快速讀入 19 20 int n,m; 21 struct node 22 { 23 int l,r,s; 24 bool operator < (const node &h)const 25 { 26 if(l!=h.l)return l>h.l; 27 return r>h.r; 28 29 }//重載運算符,確定優先隊列的優先級 30 31 }tmp;
32 priority_queue<node>q; 33 int main() 34 { 35 int t; 36 read(t); 37 while(t--) 38 { 39 while (!q.empty()) q.pop();//多組數據清空 40 read(n);read(m); 41 if(m==1){printf("true\n");continue;}//其實沒必要特判,只是優化一點點 42 for(int i=1;i<=m;i++) 43 { 44 int l,r,s; 45 read(tmp.l);read(tmp.r);read(tmp.s); 46 q.push(tmp); 47 } 48 tmp=q.top();//取出第一個 49 q.pop(); 50 while(!q.empty()) 51 { 52 node tmp1; 53 tmp1=q.top(); 54 q.pop(); 55 if(tmp.l==tmp1.l) 56 { 57 if(tmp.r==tmp1.r) 58 { 59 if(tmp.s!=tmp1.s) 60 {printf("false\n");goto end;}//退出多重循環的小操作 61 } 62 else 63 if(tmp.r<tmp1.r) 64 q.push((node) {tmp.r+1, tmp1.r, tmp1.s - tmp.s});//將抵消後的部分放入隊列 65 } 66 tmp = tmp1;//繼續比 67 } 68 printf("true\n"); 69 end:; 70 } 71 return 0; 72 }

洛谷P2294 [HNOI2005]狡猾的商人 ,神奇做法——貪心