标签:
试题描述
|
WZJ又有一个问题想问问大家。WZJ用数据生成器生成了一个虚拟旅游区。这个旅游区由N个城市构成,标号从1到N,这些城市之间由M条双向道路连接。
其中每个城市有一个游乐场,游客可以花costi的钱数去城市i的游乐场玩,并获得happyi的高兴值,但对于一个游乐场,游客只能去玩至多一次。 因为虚拟旅游区的内存有限,有时候WZJ被迫在系统中删去一些边,当然WZJ可能忘记一些已被删去的边。 另外有些同学想来体验,WZJ会给他money的钱数,并把他送到城市x,他能通过未删除的道路去一些城市的游乐场玩。 下面请你帮助WZJ完成Q次操作,操作分两种: 1、0 y:虚拟旅游区的内存有限,WZJ被迫在系统中删去边y(不保证边y未被删去,这时你可以忽略这次指令)。 2、1 x money:又来了一个同学想来体验,WZJ给了他money的钱数,并把他送到城市x,问在最多花money的钱数能得到的最大高兴值。 |
输入
|
输入第一行为三个正整数N,M,Q。
接下来N行每行为两个正整数costi,happyi。 再接下来M行每行为两个正整数ui,vi。 最后Q行每行为一个操作。 |
输出
|
对于每个操作2,输出结果单占一行。
|
输入示例
|
3 4 10
1 2 2 7 1 4 1 2 2 3 1 3 1 1 1 1 2 1 1 1 0 1 1 1 1 1 1 2 0 2 1 1 2 0 2 0 3 1 1 3 |
输出示例
|
7
4 4 7 6 2 |
其他说明
|
1<=N<=10000, 1<=M,Q<=100000, 1<=ui,vi,x<=N, 1<=costi,money<=200, 1<=happyi<=100000,1<=y<=M
|
#include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #define REP(s, n) for(int i = s; i <= n; i ++) #define RAP(s, n) for(int j = s; j <= n; j ++) #define DE(i) e[POS(i)].del #define POS(i) query[i].pos #define V(i) query[i].v #define ID(i) query[i].id #define ANS(i) query[i].ans #define COST(i) p[i].cost #define HA(i) p[i].happy using namespace std; const int maxn = 20000 + 1; const int maxm = 100000 + 1; const int maxma = 200 + 1; struct Point { int cost, happy; } p[maxn]; struct Edge { int u, v, del; Edge() { del = 0; } }e[maxm]; struct Tedge { int to, next; } adj[maxm]; struct Questions { int pos, v, ans; bool id; Questions() { ans = 0; } }query[maxm]; int Q, n, m, dp[maxn][maxma], f[maxn], tar_num[maxn], fch[maxn]; int findset(int x){ return x == f[x] ? x : f[x] = findset(f[x]); } int ms = 1; void AddEdge(int from, int to){ adj[ms] = (Tedge) { to, fch[from] }; fch[from] = ms ++; return ; } int que[maxn], tot; void dfs(int x){ que[++ tot] = x; for(int i = fch[x]; i; i = adj[i].next) dfs(adj[i].to); return ; } void merge(int u, int v){ int f1 = findset(u), f2 = findset(v); if(f1 == f2) return ; if(tar_num[f1] > tar_num[f2]) swap(f1, f2); tar_num[f2] += tar_num[f1]; tar_num[f1] = 0; f[f1] = f2; tot = 0; dfs(f1); AddEdge(f2, f1); REP(1, tot){ int v = p[que[i]].cost, w = p[que[i]].happy; for(int j = 200; j >= v; j --) dp[f2][j] = max(dp[f2][j], dp[f2][j - v] + w); } return ; } void read(int &x){ x = 0; int sig = 1; char ch = getchar(); while(!isdigit(ch)) { if(ch == ‘-‘) sig = -1; ch = getchar(); } while(isdigit(ch)) x = 10 * x + ch - ‘0‘, ch = getchar(); x *= sig; return ; } void init() { read(n), read(m), read(Q); int temp; REP(1, n) f[i] = i, tar_num[i] = 1; REP(1, n){ read(COST(i)); read(HA(i)); RAP(COST(i), 200) dp[i][j] = HA(i); } REP(1, m) read(e[i].u), read(e[i].v); REP(1, Q) { read(temp); ID(i) = temp; if(!ID(i)) { read(POS(i)); if(!DE(i)) DE(i) = i; } else read(POS(i)), read(V(i)); } return ; } void work() { REP(1, m) if(!e[i].del) merge(e[i].u, e[i].v); for(int i = Q; i; i --){ if(!ID(i) && DE(i) == i) merge(e[POS(i)].u, e[POS(i)].v); else ANS(i) = dp[findset(POS(i))][V(i)]; } return ; } void print() { REP(1, Q) if(ID(i)) printf("%d\n", ANS(i)); return ; } int main() { init(); work(); print(); return 0; }
崆若的水题之--你绝对看不懂题干的并查集#2(转载自CHX的博客)
标签:
原文地址:http://www.cnblogs.com/Kong-Ruo/p/4517418.html