HDU 4001 To Miss Our Children Time
题意:给你n个blocks。有3种,d[i] == 0:只能放在小于等于它的长和宽的积木上; d[i] == 1:只能放在长和宽小于等于它且面积小于他的木块上; d[i] == 2:只能放在长和宽偶小于它的木块上。求积木的最高高度。
做法:记忆化搜索。因为d[i] = 0有可能存在环,就用map来记录长和宽一样的积木,然后把h[i]加在第一次出现的那个积木上,同时标记一下。注意细节,a[i] * b[i]会爆int,同时答案也要用longlong,输入的a[i] 有可能比 b[i]小,要换过来(被这个条件坑shi了)
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<string> 6 #include<queue> 7 #include<cmath> 8 #include<map> 9 10 using namespace std; 11 12 #define mnx 1050 13 #define LL long long 14 #define inf 0x3f3f3f3f 15 #define MP make_pair 16 #define lson l, m, rt << 1 17 #define rson m+1, r, rt << 1 | 1 18 #define mod 9973 19 20 int a[mnx], b[mnx], d[mnx], n; 21 LL dp[mnx], h[mnx]; 22 map< pair<int,int>, int > mp; 23 bool vis[mnx]; 24 LL f( int k ){ 25 if( dp[k] > 0 ) return dp[k]; 26 dp[k] = h[k]; 27 LL tmp = dp[k]; 28 for( int i = 1; i <= n; ++i ){ 29 if( i == k || vis[i] ) continue ; 30 if( d[k] == 0 ){ 31 if( a[k] >= a[i] && b[k] >= b[i] ) 32 dp[k] = max( dp[k], tmp + f(i) ); 33 } 34 else if( d[k] == 1 ){ 35 if( a[k] >= a[i] && b[k] >= b[i] && (LL)a[k] * b[k] > (LL)a[i] * b[i] ) 36 dp[k] = max( dp[k], tmp + f(i) ); 37 } 38 else{ 39 if( a[k] > a[i] && b[k] > b[i] ) 40 dp[k] = max( dp[k], tmp + f(i) ); 41 } 42 } 43 return dp[k]; 44 } 45 int main(){ 46 while( scanf( "%d", &n ) != EOF && n ){ 47 mp.clear(); 48 memset( vis, 0, sizeof(vis) ); 49 memset( dp, -1, sizeof(dp) ); 50 for( int i = 1; i <= n; ++i ){ 51 scanf( "%d%d%d%d", &a[i], &b[i], &h[i], &d[i] ); 52 if( a[i] < b[i] ) 53 swap( a[i], b[i] ); 54 if( d[i] == 0 ){ 55 if( mp.count( MP(a[i], b[i]) ) ){ 56 int j = mp[MP(a[i],b[i])]; 57 h[j] += h[i]; 58 vis[i] = 1; 59 continue; 60 } 61 mp[MP(a[i],b[i])] = i; 62 } 63 } 64 LL ans = 0; 65 for( int i = 1; i <= n; ++i ){ 66 if( dp[i] < 0 ) 67 ans = max( ans, f(i) ); 68 } 69 printf( "%I64d ", ans ); 70 } 71 return 0; 72 }
题意:φ(n)是欧拉函数,给你一个N,叫你求 2 ~ N中,n/φ(n)最大的n。
做法:φ(n) = n * (1 - 1/p1) * (1 - 1/p2) * (1 - 1/p3) * … * (1 - 1/pt)
则f(n) = n/φ(n) = 1 / [ (1 - 1/p1) * (1 - 1/p2) * (1 - 1/p3) * … * (1 - 1/pt) ]
要使f(x)最大,须使x含尽量多的不同素数因子。用java先打表求出质因子的乘积。然后贴到c++。
1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 #include <cmath> 6 #include <queue> 7 #include <iomanip> 8 #include <map> 9 #include <set> 10 #include <algorithm> 11 using namespace std; 12 13 #define mxn 1020 14 #define N 55 15 #define mxe 20020 16 #define MP make_pair 17 #define PB push_back 18 #define LL long long 19 #define ULL unsigned LL 20 #define inf 0x3f3f3f3f 21 #define ls (i << 1) 22 #define rs (ls | 1) 23 #define md ((ll + rr) >> 1) 24 25 char s[][mxn] = { 26 "2", 27 "6", 28 "30", 29 "210", 30 "2310", 31 "30030", 32 "510510", 33 "9699690", 34 "223092870", 35 "6469693230", 36 "200560490130", 37 "7420738134810", 38 "304250263527210", 39 "13082761331670030", 40 "614889782588491410", 41 "32589158477190044730", 42 "1922760350154212639070", 43 "117288381359406970983270", 44 "7858321551080267055879090", 45 "557940830126698960967415390", 46 "40729680599249024150621323470", 47 "3217644767340672907899084554130", 48 "267064515689275851355624017992790", 49 "23768741896345550770650537601358310", 50 "2305567963945518424753102147331756070", 51 "232862364358497360900063316880507363070", 52 "23984823528925228172706521638692258396210", 53 "2566376117594999414479597815340071648394470", 54 "279734996817854936178276161872067809674997230", 55 "31610054640417607788145206291543662493274686990", 56 "4014476939333036189094441199026045136645885247730", 57 "525896479052627740771371797072411912900610967452630", 58 "72047817630210000485677936198920432067383702541010310", 59 "10014646650599190067509233131649940057366334653200433090", 60 "1492182350939279320058875736615841068547583863326864530410", 61 "225319534991831177328890236228992001350685163362356544091910", 62 "35375166993717494840635767087951744212057570647889977422429870", 63 "5766152219975951659023630035336134306565384015606066319856068810", 64 "962947420735983927056946215901134429196419130606213075415963491270", 65 "166589903787325219380851695350896256250980509594874862046961683989710", 66 "29819592777931214269172453467810429868925511217482600306406141434158090", 67 "5397346292805549782720214077673687806275517530364350655459511599582614290", 68 "1030893141925860008499560888835674370998623848299590975192766715520279329390", 69 "198962376391690981640415251545285153602734402721821058212203976095413910572270", 70 "39195588149163123383161804554421175259738677336198748467804183290796540382737190", 71 "7799922041683461553249199106329813876687996789903550945093032474868511536164700810", 72 "1645783550795210387735581011435590727981167322669649249414629852197255934130751870910", 73 "367009731827331916465034565550136732339800312955331782619462457039988073311157667212930", 74 "83311209124804345037562846379881038241134671040860314654617977748077292641632790457335110", 75 "19078266889580195013601891820992757757219839668357012055907516904309700014933909014729740190", 76 "4445236185272185438169240794291312557432222642727183809026451438704160103479600800432029464270", 77 "1062411448280052319722448549835623701226301211611796930357321893850294264731624591303255041960530", 78 "256041159035492609053110100510385311995538591998443060216114576417920917800321526504084465112487730", 79 "64266330917908644872330635228106713310880186591609208114244758680898150367880703152525200743234420230", 80 "16516447045902521732188973253623425320896207954043566485360902980990824644545340710198976591011245999110", 81 "4343825573072363215565699965702960859395702691913457985649917484000586881515424606782330843435957697765930", 82 "1168489079156465704987173290774096471177444024124720198139827803196157871127649219224446996884272620699035170", 83 "316660540451402206051523961799780143689087330537799173695893334666158783075592938409825136155637880209438531070", 84 "87714969705038411076272137418539099801877190558970371113762453702525982911939243939521562715111692818014473106390", 85 "24647906487115793512432470614609487044327490547070674282967249490409801198254927547005559122946385681862066942895590", 86 "6975357535853769564018389183934484833544679824821000822079731605785973739106144495802573231793827147966964944839451970", 87 "2043779758005154482257388030892804056228591188672553240869361360495290305558100337270153956915591354354320728837959427210", 88 "627440385707582426053018125484090845262177494922473844946893937672054123806336803541937264773086545786776463753253544153470", 89 "195133959955058134502488637025552252876537200920889365778484014616008832503770745901542489344429915739687480227261852231729170", 90 "61076929465933196099278943388997855150356143888238371488665496574810764573680243467182799164806563626522181311132959748531230210", 91 "19361386640700823163471425054312320082662897612571563761906962414215012369856637179096947335243680669607531475629148240284399976570", 92 "6408618978071972467109041692977377947361419109761187605191204559105169094422546906281089567965658301640092918433248067534136392244670", 93 "2159704595610254721415747050533376368260798239989520222949435936418441984820398307416727184404426847652711313512004598759003964186453790", 94 "749417494676758388331264226535081599786496989276363517363454269937199368732678212673604332988336116135490825788665595769374375572699465130", 95 "261546705642188677527611215060743478325487449257450867559845540208082579687704696223087912212929304531286298200244292923511657074872113330370", 96 "92325987091692603167246758916442447848897069587880156248625475693453150629759757766750033011164044499544063264686235401999614947429856005620610", 97 "33145029365917644537041586451002838777754047982048976093256545773949681076083753038263261851007891975336318712022358509317861766127318306017798990", 98 "12164225777291775545094262227518041831435735609411974226225152299039532954922737365042617099319896354948428967312205572919655268168725818308532229330", 99 "4537256214929832278320159810864229603125529382310666386381981807541745792186181037160896178046321340395764004807452678699031415026934730229082521540090", 100 "1719620105458406433483340568317543019584575635895742560438771105058321655238562613083979651479555788009994557822024565226932906295208262756822275663694110", 101 "658614500390569664024119437665618976500892468548069400648049333237337193956369480811164206516669866807827915645835408481915303111064764635862931579194844130", 102 "256201040651931599305382461251925781858847170265198996852091190629324168449027728035542876334984578188245059186229973899465052910204193443350680384306794366570", 103 "101711813138816844924236837117014535397962326595284001750280202679841694874264008030110521904988877540733288496933299638087626005351064797010220112569797363528290", 104 "40786437068665554814618971683922828694582892964708884701862361274616519644579867220074319283900539893834048687270253154873138028145776983601098265140488742774844290", 105 "16681652761084211919179159418724436936084403222565933843061705761318156534633165693010396587115320816578125913093533540343113453511622786292849190442459895794911314610", 106 "6989612506894284794136067796445539076219364950255126280242854713992307588011296425371356170001319422146234757586190553403764537021369947456703810795390696338067840821590", 107 "2942626865402493898331284542303571951088352644057408163982241834590761494552755795081340947570555476723564832943786222982984870085996747879272304344859483158326560985889390", 108 "1268272178988474870180783637732839510919079989588742918676346230708618204152237747680057948402909410467856442998771862105666479007064598335966363172634437241238747784918327090", 109 "549161853502009618788279315138319508227961635491925683786857917896831682397918944745465091658459774732581839818468216291753585410058971079473435253750711325456377790869635629970", 110 "241082053687382222648054619345722264112075157980955375182430625956709108572686416743259175238063841107603427680307546952079823995015888303888838076396562271875349850191770041556830", 111 "106799349783510324633088196370154963001649294985563231205816767298822135097700082617263814630462281610668318462376243299771362029792038518622755267843677086440779983634954128409675690", 112 "47952908052796135760256600170199578387740533448517890811411728517171138658867337095151452769077564443190074989606933241597341551376625294861617115261811011811910212652094403655944384810", 113 "21914478980127834042437266277781207323197423785972676100815159932347210367102373052484213915468446950537864270250368491409985088979117759751759021674647632398042967182007142470766583858170", 114 "10102574809838931493563579754057136575994012365333403682475788728812063979234193977195222615030954044197955428585419874540003126019373287245560908992012558535497807870905292679023395158616370", 115 "4677492136955425281519937426128454234685227725149365904986290181439985622385431811441388070759331722463653363435049401912021447346969831994694700863301814601935485044229150510387831958439379310", 116 "2184388827958183606469810778001988127598001347644753877628597514732473285653996655943128229044607914390526120724168070692914015911034911541522425303161947419103871515655013288351117524591190137770", 117 "1046322248591969947499039362662952313119442645521837107384098209556854703828264398196758421712367190993062011826876505861905813621385722628389241720214572813750754455998751365120185294279180075991830", 118 "509558935064289364432032169616857776489168568369134671296055828054188240764364761921821351373922822013621199759688858354748131233614846920025560717744496960296617420071391914813530238313960697008021210", 119 "250193437116566077936127795281877168256181767069245123606363411574606426215303098103614283524596105608688009082007229452181332435704889837732550312412548007505639153255053430173443347012154702230938414110", 120 "124846525121166472890127769845656706959834701767553316679575342375728606681436245953703527478773456698735316531921607496638484885416740029028542605893861455745313937474271661656548230159065196413238268640890", 121 "62797802135946735863734268232365323600796854989079318289826397214991489160762431714712874321823048719463864215556568570809157897364620234601356930764612312239892910549558645813243759770009793795858849126367670", 122 "31964081287196888554640742530273949712805599189441373009521636182430667982828077742788853029807931798207106885718293402541861369758591699412090677759187666930105491469725350718941073722934985042092154205321144030", 123 "16653286350629578936967826858272727800371717177698955337960772451046378019053428503992992428529932466865902687459230862724309773644226275393699243112536774470584961055726907724568299409649127206930012340972316039630", 124 "8709668761379269784034173446876636639594408083936553641753483991897255703964943107588335040121154680170867105541177741204814011615930342030904704147856733048115934632145172739949220591246493529224396454328521288726490", 125 "4711930799906184953162487834760260422020574773409675520188634839616415335845034221205289256705544681972439104097777157991804380284218315038719444943990492579030720635990538452312528339864352999310398481791730017201031090", 126 }; 127 char t[mxn]; 128 129 bool check(int k) { 130 if(strlen(s[k]) < strlen(t)) return 1; 131 if(strlen(s[k]) > strlen(t)) return 0; 132 for(int i = 0; t[i]; ++i) { 133 if(s[k][i] < t[i]) return 1; 134 if(s[k][i] > t[i]) return 0; 135 } 136 return 1; 137 } 138 int main() { 139 int cas; 140 scanf("%d", &cas); 141 while(cas--) { 142 scanf("%s", t); 143 for(int i = 0;; ++i) { 144 if(!check(i)) { 145 printf("%s ", s[i-1]); 146 break; 147 } 148 } 149 } 150 return 0; 151 }
题意:一棵树,K个机器人遍历所有结点所需的最少权值和。
做法:前几天刚刚做过。dp+背包。dp[i][j]表示当前以i为根的子树,用j个机器人遍历所需要的最少权值和。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<string> 6 #include<queue> 7 #include<cmath> 8 #include<vector> 9 10 using namespace std; 11 12 #define mnx 20050 13 #define ll long long 14 #define inf 0x3f3f3f3f 15 #define lson l, m, rt << 1 16 #define rson m+1, r, rt << 1 | 1 17 #define mod 9973 18 19 int fst[mnx], nxt[mnx], vv[mnx], cost[mnx], e; 20 void add( int u, int v, int c ){ 21 vv[e] = v, nxt[e] = fst[u], cost[e] = c, fst[u] = e++; 22 } 23 int k, dp[mnx][12]; 24 void dfs( int u, int fa ){ 25 for( int i = fst[u]; i != -1; i = nxt[i] ){ 26 int v = vv[i], c = cost[i]; 27 if( v == fa ) continue; 28 dfs( v, u ); 29 for( int j = k; j >= 0; --j ){ 30 dp[u][j] += dp[v][0] + 2 * c; 31 for( int jj = 1; jj <= j; ++jj ){ 32 dp[u][j] = min( dp[u][j], dp[u][j-jj] + dp[v][jj] + jj * c ); 33 } 34 } 35 } 36 } 37 int main(){ 38 int n, s; 39 while( scanf( "%d%d%d", &n, &s, &k ) != EOF ){ 40 memset( dp, 0, sizeof(dp) ); 41 memset( fst, -1, sizeof(fst) ); 42 e = 0; 43 for( int i = 1; i < n; ++i ){ 44 int u, v, c; 45 scanf( "%d%d%d", &u, &v, &c ); 46 add( u, v, c ); 47 add( v, u, c ); 48 } 49 dfs( s, -1 ); 50 printf( "%d ", dp[s][k] ); 51 } 52 return 0; 53 }
题意:长为L的河,有n个石头,青蛙最多能跳m次,求能过河的最小的跳跃长度。
做法:二分,注意细节就好。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<string> 6 #include<queue> 7 #include<cmath> 8 #include<vector> 9 10 using namespace std; 11 12 #define mnx 500500 13 #define ll long long 14 #define inf 0x3f3f3f3f 15 #define lson l, m, rt << 1 16 #define rson m+1, r, rt << 1 | 1 17 #define mod 9973 18 19 int a[mnx], n, m, L; 20 bool check( int s ){ 21 int i = 0, j = 0, cur = 0; 22 for( i = 0; i < m && cur < L; ++i ){ 23 cur += s; 24 while( a[j] <= cur && j <= n ){ 25 j++; 26 } 27 cur = a[j-1]; 28 } 29 if( cur == L ) 30 return 1; 31 else return 0; 32 } 33 int main(){ 34 while( scanf( "%d%d%d", &L, &n, &m ) != EOF ){ 35 for( int i = 0; i < n; ++i ){ 36 scanf( "%d", &a[i] ); 37 } 38 a[n] = L; 39 sort( a, a + n + 1 ); 40 int l = 0, r = L; 41 while( l < r ){ 42 int mid = ( l + r ) >> 1; 43 if( check( mid) ) 44 r = mid; 45 else l = mid + 1; 46 } 47 printf( "%d ", l ); 48 } 49 return 0; 50 }
题意:有两个操作,一个插入,一个询问第k大的数。
做法:离线,hash,线段树。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<string> 6 #include<queue> 7 #include<cmath> 8 #include<map> 9 10 using namespace std; 11 12 #define mnx 1000050 13 #define LL long long 14 #define inf 0x3f3f3f3f 15 #define MP make_pair 16 #define lson l, m, rt << 1 17 #define rson m+1, r, rt << 1 | 1 18 #define mod 9973 19 20 int n, k, a[mnx], b[mnx], g[mnx], sum[mnx<<2]; 21 void pushup( int rt ){ 22 sum[rt] = sum[rt<<1] + sum[rt<<1|1]; 23 } 24 void update( int v, int l, int r, int rt ){ 25 if( l == r ){ 26 sum[rt]++; 27 return ; 28 } 29 int m = ( l + r ) >> 1; 30 if( v <= m ) update( v, lson ); 31 else update( v, rson ); 32 pushup( rt ); 33 } 34 int query( int v, int l, int r, int rt ){ 35 if( l == r ){ 36 return l; 37 } 38 int m = ( l + r ) >> 1; 39 if( sum[rt<<1] >= v ) return query( v, lson ); 40 else return query( v - sum[rt<<1], rson ); 41 } 42 int main(){ 43 while( scanf( "%d%d", &n, &k ) != EOF ){ 44 memset( sum, 0, sizeof(sum) ); 45 int all = 0, v, cnt = 0; 46 char s[3]; 47 for( int i = 0; i < n; ++i ){ 48 scanf( "%s", s ); 49 if( s[0] == 'I' ){ 50 b[i] = 0; 51 scanf( "%d", &a[i] ); 52 g[cnt++] = a[i]; 53 } 54 else b[i] = 1; 55 } 56 sort( g, g + cnt ); 57 cnt = unique( g, g + cnt ) - g; 58 for( int i = 0; i < n; ++i ){ 59 if( b[i] ){ 60 v = query( all - k + 1, 1, cnt, 1 ); 61 printf( "%d ", g[v-1]); 62 } 63 else{ 64 v = lower_bound( g, g + cnt, a[i] ) - g + 1; 65 update( v, 1, cnt, 1 ); 66 all++; 67 } 68 } 69 } 70 return 0; 71 }
题意:已知 n 个人的坐标,求边长为R的正方形最多可以包含多少人。正方形的边与坐标轴是平行的。
做法:离散化+扫描线+线段树。以每个人的坐标为左下角建正方形,求正方形的覆盖次数最多。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<string> 6 #include<queue> 7 #include<cmath> 8 #include<map> 9 10 using namespace std; 11 12 #define mnx 5050 13 #define LL long long 14 #define inf 0x3f3f3f3f 15 #define MP make_pair 16 #define lson l, m, rt << 1 17 #define rson m+1, r, rt << 1 | 1 18 #define mod 9973 19 20 struct edge{ 21 int l, r, h, s; 22 edge( int l = 0, int r = 0, int h = 0, int s = 0 ) : l(l), r(r), h(h), s(s) {} 23 bool operator < ( const edge &b ) const { 24 if( h == b.h ) 25 return s > b.s; 26 return h < b.h; 27 } 28 }e[mnx]; 29 int sum[mnx<<2], vis[mnx<<2], X[mnx]; 30 void pushup( int rt ){ 31 if( vis[rt] ){ 32 sum[rt] = vis[rt] + max( sum[rt<<1|1], sum[rt<<1] ); 33 } 34 else sum[rt] = max( sum[rt<<1], sum[rt<<1|1] ); 35 } 36 void update( int L, int R, int v, int l, int r, int rt ){ 37 if( L <= l && R >= r ){ 38 vis[rt] += v; 39 pushup( rt ); 40 return ; 41 } 42 int m = ( l + r ) >> 1; 43 if( L <= m ) update( L, R, v, lson ); 44 if( R > m ) update( L, R, v, rson ); 45 pushup( rt ); 46 } 47 int main(){ 48 int n, R, m; 49 while( scanf( "%d%d", &n, &R ) != EOF ){ 50 memset( sum, 0, sizeof(sum) ); 51 memset( vis, 0, sizeof(vis) ); 52 int x, y; 53 m = 0; 54 for( int i = 1; i <= n; ++i ){ 55 scanf( "%d%d", &x, &y ); 56 X[m] = x, e[m++] = edge( x, x + R, y, 1 ); 57 X[m] = x + R, e[m++] = edge( x, x + R, y + R, -1 ); 58 } 59 sort( X, X + m ); 60 int cnt = unique( X, X + m ) - X; 61 sort( e, e + m ); 62 int ans = 0; 63 for( int i = 0; i < m-1; ++i ){ 64 int L = lower_bound( X, X + cnt, e[i].l ) - X; 65 int R = lower_bound( X, X + cnt, e[i].r ) - X; 66 if( L <= R ) 67 update( L, R, e[i].s, 0, cnt-1, 1 ); 68 ans = max( ans, sum[1] ); 69 } 70 printf( "%d ", ans ); 71 } 72 return 0; 73 }
题意:给你一棵树,有m个询问,输入x,y,求出以x为根,y的儿子结点中最小的 和 y的子孙结点中最小的值。
做法:树形dp。以1为根dfs,dp[i][0][0],表示 i 结点所在的子树,儿子结点最小的。dp[i][1][0],表示 i 结点所在的子树,子孙结点最小的。f[i]表示除了 i 结点和 i 结点 所在的子树,其他所有结点最小的。dfs1处理处dp数组,dfs2处理出f数组。对于询问,分3种情况。x == y,x和y在不同的子树 或者 x与y的lca是x, x与y的lca是y。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<string> 6 #include<queue> 7 #include<cmath> 8 #include<map> 9 10 using namespace std; 11 12 #define mnx 200050 13 #define LL long long 14 #define inf 0x3f3f3f3f 15 #define MP make_pair 16 #define lson l, m, rt << 1 17 #define rson m+1, r, rt << 1 | 1 18 #define mod 9973 19 20 int fst[mnx], nxt[mnx], vv[mnx], e; 21 void init(){ 22 memset( fst, -1, sizeof(fst) ); 23 e = 0; 24 } 25 void add( int u, int v ){ 26 vv[e] = v, nxt[e] = fst[u], fst[u] = e++; 27 } 28 int dp[mnx][2][3], dep[mnx], fa[22][mnx], f[mnx]; 29 void update( int k, int d, int val ){ 30 dp[k][d][2] = val; 31 sort( dp[k][d], dp[k][d]+3 ); 32 } 33 void dfs1( int d, int u, int p ){ 34 dep[u] = d; 35 fa[0][u] = p; 36 for( int i = fst[u]; i != -1; i = nxt[i] ){ 37 int v = vv[i]; 38 if( v == p ) continue; 39 dfs1( d+1, v, u ); 40 update( u, 0, v ); 41 update( u, 1, min(v, dp[v][1][0]) ); 42 } 43 } 44 int n, m; 45 void lcaInit(){ 46 for( int k = 0; k < 21; ++k ){ 47 for( int i = 1; i <= n; ++i ){ 48 if( fa[k][i] == -1 ) 49 fa[k+1][i] = -1; 50 else 51 fa[k+1][i] = fa[k][fa[k][i]]; 52 } 53 } 54 } 55 void dfs2( int u ){ 56 for( int i = fst[u]; i != -1; i = nxt[i] ){ 57 int v = vv[i]; 58 if( v == fa[0][u] ) continue; 59 f[v] = f[u]; 60 if( fa[0][u] != -1 ) 61 f[v] = min( f[v], fa[0][u] ); 62 int x = min( v, dp[v][1][0] ); 63 if( x == dp[u][1][0] ) 64 f[v] = min( f[v], dp[u][1][1] ); 65 else 66 f[v] = min( f[v], dp[u][1][0] ); 67 dfs2( v ); 68 } 69 } 70 int lca( int u, int v ){ 71 if( dep[u] > dep[v] ) swap( u, v ); 72 for( int k = 0; k < 22; ++k ) 73 if( (dep[v] - dep[u] ) >> k & 1 ) 74 v = fa[k][v]; 75 if( u == v ) return v; 76 for( int k = 21; k >= 0; --k ){ 77 if( fa[k][u] != fa[k][v] ) 78 u = fa[k][u], v = fa[k][v]; 79 } 80 return fa[0][u]; 81 } 82 int kfa( int u, int k ){ 83 for( int i = 0; i < 22; ++i ){ 84 if( k >> i & 1 ) 85 u = fa[i][u]; 86 } 87 return u; 88 } 89 int main(){ 90 int cas; 91 scanf( "%d", &cas ); 92 while( cas-- ){ 93 scanf( "%d%d", &n, &m ); 94 init(); 95 for( int i = 1; i < n; ++i ){ 96 int u, v; 97 scanf( "%d%d", &u, &v ); 98 add( u, v ), add( v, u ); 99 } 100 memset( dp, 0x3f, sizeof(dp) ); 101 dfs1( 0, 1, -1 ); 102 lcaInit(); 103 memset( f, 0x3f, sizeof(f) ); 104 dfs2( 1 ); 105 while( m-- ){ 106 int x, y; 107 scanf( "%d%d", &x, &y ); 108 int p = lca( x, y ); 109 int ans1 = inf, ans2 = inf; 110 if( x == y ){ 111 ans1 = dp[x][0][0]; 112 if( x == 1 ) 113 ans2 = 2; 114 else 115 ans2 = 1; 116 if( fa[0][x] != -1 ) 117 ans1 = min( ans1, fa[0][x] ); 118 } 119 else if( p == x || ( p != x && p != y ) ){ 120 ans1 = dp[y][0][0]; 121 ans2 = dp[y][1][0]; 122 } 123 else{ 124 int w = kfa( x, dep[x] - dep[y] - 1 ); 125 ans2 = f[w]; 126 if( w == dp[y][0][0] ) ans1 = dp[y][0][1]; 127 else ans1 = dp[y][0][0]; 128 if( fa[0][y] != -1 ) ans1 = min( ans1, fa[0][y] ); 129 } 130 if( ans1 == inf || ans2 == inf ) 131 puts( "no answers!" ); 132 else printf( "%d %d ", ans1, ans2 ); 133 } 134 puts( "" ); 135 } 136 return 0; 137 }
题意:有n个房子,最开始的时候都没有水,坐标为( a, b, c ),建一个水井,需要 x * c 的花费;如果u 与 v之间能够建水渠,如果u的c大于等于v的c,那么需要花费 dis(u, v) * y,否则需要花费dis(u, v) * y + z;问你要使这n个房子有水,最少需要花费多少。
做法:最小树形图。虚拟一个源点,源点到所有房子的花费是 x * c,然后按照题意连边,做最小树形图就好了。
1 #include<iostream> 2 #include<cstring> 3 #include<algorithm> 4 #include<cstdio> 5 #include<string> 6 #include<queue> 7 #include<cmath> 8 #include<map> 9 10 using namespace std; 11 12 #define mnx 1050 13 #define LL long long 14 #define inf 0x3f3f3f3f 15 #define MP make_pair 16 #define lson l, m, rt << 1 17 #define rson m+1, r, rt << 1 | 1 18 #define mod 9973 19 20 struct point{ 21 int x, y, c; 22 point( int x = 0, int y = 0, int c = 0 ) : x(x), y(y), c(c) {} 23 void input(){ 24 scanf( "%d%d%d", &x, &y, &c ); 25 } 26 }; 27 int dis( point a, point b ){ 28 return abs( a.x - b.x ) + abs( a.y - b.y ) + abs( a.c - b.c ); 29 } 30 struct edge{ 31 int u, v, w; 32 edge( int u = 0, int v = 0, int w = 0 ) : u(u), v(v), w(w) {} 33 }; 34 int in[mnx], id[mnx], v[mnx], pre[mnx]; 35 edge e[mnx*mnx]; 36 void zhu_liu( int root, int n, int m ){ 37 int s, t, idx = n, ans = 0; 38 while( idx ){ 39 for( int i = 1; i <= n; ++i ) 40 in[i] = inf, id[i] = v[i] = -1; 41 for( int i = 1; i <= m; ++i ){ 42 s = e[i].u, t =e[i].v; 43 if( e[i].w > in[t] || s == t ) continue; 44 pre[t] = s; 45 in[t] = e[i].w; 46 } 47 in[root] = 0, pre[root] = root; 48 for( int i = 1; i <= n; ++i ) 49 ans += in[i]; 50 idx = 0; 51 for( int i = 1; i <= n; ++i ){ 52 if( v[i] == -1 ){ 53 t = i; 54 while( v[t] == -1 ) 55 v[t] = i, t = pre[t]; 56 if( v[t] != i || t == root ) continue; 57 id[t] = ++idx; 58 for( s = pre[t]; s != t; s = pre[s] ) 59 id[s] = idx; 60 } 61 } 62 if( idx == 0 ) continue; 63 for( int i = 1; i <= n; ++i ) 64 if( id[i] == -1 ) id[i] = ++idx; 65 for( int i = 1; i <= m; ++i ){ 66 e[i].w -= in[e[i].v]; 67 e[i].u = id[e[i].u]; 68 e[i].v = id[e[i].v]; 69 } 70 n = idx; 71 root = id[root]; 72 } 73 printf( "%d ", ans ); 74 } 75 point p[mnx]; 76 int main(){ 77 int n, x, y, z; 78 while( scanf( "%d%d%d%d", &n, &x, &y, &z ) != EOF ){ 79 if( n == 0 && x == 0 && y == 0 && z == 0 ) break; 80 int m = 0; 81 for( int i = 1; i <= n; ++i ){ 82 p[i].input(); 83 e[++m] = edge( n+1, i, p[i].c * x ); 84 } 85 int g, k; 86 for( int i = 1; i <= n; ++i ){ 87 scanf( "%d", &k ); 88 while( k-- ){ 89 scanf( "%d", &g ); 90 if( p[i].c >= p[g].c ) 91 e[++m] = edge( i, g, dis( p[i], p[g] ) * y ); 92 else e[++m] = edge( i, g, dis( p[i], p[g] ) * y + z ); 93 } 94 } 95 zhu_liu( n+1, n+1, m ); 96 } 97 return 0; 98 }