2011大连网络赛

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 }
View Code

HDU 4002 Find the maximum

题意:φ(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 }
View Code

HDU 4003 Find Metal Mineral

题意:一棵树,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 }
View Code

HDU 4004 The Frog's Games

题意:长为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 }
View Code

 HDU 4006 The kth great number

题意:有两个操作,一个插入,一个询问第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 }
View Code

 HDU 4007 Dave

题意:已知 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 }
View Code

 HDU 4008 Parent and son

题意:给你一棵树,有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 }
View Code

 HDU 4009 Transfer water

题意:有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 }
View Code
原文地址:https://www.cnblogs.com/LJ-blog/p/4396676.html