COJ 3016 WZJ的图论问题

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1046

试题描述:

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

题解:时光倒流+背包dp

注意,加边的时候都搞成单向边了(,,• ? •,,)好神奇呀呀(?•ˇ?ˇ•?)小健建就是NB呀呀呀(???з??)

还有,结点要开2倍,我也不造为什么诺_( ?Д?)?

  1 #include <cstdio>
  2 #include <iostream>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cmath>
  6 #include <queue>
  7 #define REP(s, n) for(int i = s; i <= n; i ++)
  8 #define RAP(s, n) for(int j = s; j <= n; j ++)
  9 #define DE(i) e[POS(i)].del
 10 #define POS(i) query[i].pos
 11 #define V(i) query[i].v
 12 #define ID(i) query[i].id
 13 #define ANS(i) query[i].ans
 14 #define COST(i) p[i].cost
 15 #define HA(i) p[i].happy
 16 using namespace std;
 17 const int maxn = 20000 + 1;
 18 const int maxm = 100000 + 1;
 19 const int maxma = 200 + 1;
 20 struct Point { int cost, happy; } p[maxn];
 21 struct Edge {
 22     int u, v, del;
 23     Edge() { del = 0; }
 24 }e[maxm];
 25 struct Tedge { int to, next; } adj[maxm];
 26 struct Questions {
 27     int pos, v, ans;
 28     bool id;
 29     Questions() { ans = 0; }
 30 }query[maxm];
 31 int Q, n, m, dp[maxn][maxma], f[maxn], tar_num[maxn], fch[maxn];
 32 int findset(int x){
 33     return x == f[x] ? x : f[x] = findset(f[x]);
 34 }
 35 int ms = 1;
 36 void AddEdge(int from, int to){
 37     adj[ms] = (Tedge) { to, fch[from] };
 38     fch[from] = ms ++;
 39     return ;
 40 }
 41 int que[maxn], tot;
 42 void dfs(int x){
 43     que[++ tot] = x;
 44     for(int i = fch[x]; i; i = adj[i].next) dfs(adj[i].to);
 45     return ;
 46 }
 47 void merge(int u, int v){
 48     int f1 = findset(u), f2 = findset(v);
 49     if(f1 == f2) return ;
 50     if(tar_num[f1] > tar_num[f2]) swap(f1, f2);
 51     tar_num[f2] += tar_num[f1]; tar_num[f1] = 0; f[f1] = f2;
 52     tot = 0; dfs(f1); AddEdge(f2, f1);
 53     REP(1, tot){
 54         int v = p[que[i]].cost, w = p[que[i]].happy;
 55         for(int j = 200; j >= v; j --) dp[f2][j] = max(dp[f2][j], dp[f2][j - v] + w);
 56     }
 57     return ;
 58 }
 59 void read(int &x){
 60     x = 0; int sig = 1; char ch = getchar();
 61     while(!isdigit(ch)) { if(ch == ‘-‘) sig = -1; ch = getchar(); }
 62     while(isdigit(ch)) x = 10 * x + ch - ‘0‘, ch = getchar();
 63     x *= sig; return ;
 64 }
 65 void init(){
 66     read(n), read(m), read(Q); int temp;
 67     REP(1, n) f[i] = i, tar_num[i] = 1;
 68     REP(1, n){
 69         read(COST(i)); read(HA(i));
 70         RAP(COST(i), 200) dp[i][j] = HA(i);
 71     }
 72     REP(1, m) read(e[i].u), read(e[i].v);
 73     REP(1, Q){
 74         read(temp); ID(i) = temp;
 75         if(!ID(i)) {
 76             read(POS(i));
 77             if(!DE(i)) DE(i) = i;
 78         }
 79         else read(POS(i)), read(V(i));
 80     }
 81     return ;
 82 }
 83 void work(){
 84     REP(1, m) if(!e[i].del) merge(e[i].u, e[i].v);
 85     for(int i = Q; i; i --){
 86         if(!ID(i) && DE(i) == i) merge(e[POS(i)].u, e[POS(i)].v);
 87         else ANS(i) = dp[findset(POS(i))][V(i)];
 88     }
 89     return ;
 90 }
 91 void print(){
 92     REP(1, Q) if(ID(i)) printf("%d\n", ANS(i));
 93     return ;
 94 }
 95 int main(){
 96     init();
 97     work();
 98     print();
 99     return 0;
100 }
时间: 2024-10-24 23:36:18

COJ 3016 WZJ的图论问题的相关文章

COJ 0970 WZJ的数据结构(负三十)树分治

WZJ的数据结构(负三十) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 给你一棵N个点的无根树,点和边上均有权值.请你设计一个数据结构,回答M次操作. 1 x v:对于树上的每一个节点y,如果将x.y在树上的距离记为d,那么将y节点的权值加上d*v. 2 x:询问节点x的权值. 输入 第一行为一个正整数N.第二行到第N行每行三个正整数ui,vi,wi.表示一条树边从ui到vi,距离为wi.第N+1行为一个正整数M.最后

COJ 0981 WZJ的数据结构(负十九)树综合

WZJ的数据结构(负十九) 难度级别:E: 运行时间限制:15000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 WZJ的数据结构中有很多都是关于树的.这让很多练习模板的同学还要找来找去很不爽,于是WZJ跟小伙伴们一块商量如何将这些题汇拢到一块去: WZJ:为了大家简单,我规定一开始是一棵有根树. LZJ:那我一定得加上换根操作喽. XJR:链信息修改,链信息增加,链信息翻倍,维护链信息的最大,最小,总和肯定很好做. CHX:子树信息修改,子树信息增加,子树

COJ 0346 WZJ的旅行(二)

WZJ的旅行(二) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 时隔多日,WZJ又来到了幻想国旅行.幻想国由N个城市组成,由于道路翻修,只有N-1条双向道路可以通行,第i条双向道路从ui连接到vi,距离为wi.但这N-1条道路竟然连接了整个国家,每两个城市之间都有一条道路! WZJ知道这里景点很多,所以他想从城市s出发到城市t,旅游所有沿途的城市.WZJ想起到锻炼作用,但又不想太累,所以城市s到城市t的距离必须在L到R之

COJ 0979 WZJ的数据结构(负二十一)

WZJ的数据结构(负二十一) 难度级别:C: 运行时间限制:5000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你实现一个数据结构,完成这样的功能: 给你一个N个点的图,初始状态无边. 每次加入一条双向边(u,v,w),若加入后没有构成一棵生成树,输出“Not Yet”,否则输出当前最小生成树的权值. 输入 第一行两个正整数N,M.表示有N个点M个操作.接下来M行每行三个正整数u,v,w. 输出 每次加入一条双向边(u,v,w),若加入后没有构成一棵生成

COJ 0985 WZJ的数据结构(负十五)(限定区域不同数)

传送门:http://oj.cnuschool.org.cn/oj/home/addSolution.htm?problemID=955 试题描述: CHX有一个问题想问问大家.给你一个长度为N的数列A,请你找到两个位置L,R,使得A[L].A[L+1].…….A[R]中没有重复的数,输出R-L+1的最大值. 以上是附中联赛加试的一道题.WZJ觉得这道题太水了,改了改题目: WZJ有一个问题想问问大家.给你一个长度为N的数列A,你要回答M次问题.每次问题给你两个正整数ql,qr.请你找到两个位置

COJ 1010 WZJ的数据结构(十) 线段树区间操作

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int

COJ 0995 WZJ的数据结构(负五)区间操作

WZJ的数据结构(负五) 难度级别:C: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,完成以下功能: 给定一个大小为N的整数组A,要求你回答执行M次操作.操作分两种: 操作1:每次操作给你l,r,v三个参数,求Al至Ar中值<=v的个数. 操作2:每次操作给你l,r,v三个参数,将Al至Ar中每个数的值+v. 输入 第一行为一个正整数N.第二行为N个整数Ai.第三行为一个正整数M.接下来M行每行4个正整数t,l,

COJ 0999 WZJ的数据结构(负一)

WZJ的数据结构(负一) 难度级别:D: 运行时间限制:1000ms: 运行空间限制:262144KB: 代码长度限制:2000000B 试题描述 输入N个模板串Pi和文本串T,输出每个模板串Pi在T中出现了多少次. 输入 第一行为一个正整数N.接下来N行为Pi.最后一行为T 输出 输出N行,第i行为模板串Pi在T中出现的次数. 输入示例 5aabbaabaaababababa 输出示例 54445 其他说明 1<=sigma(|Pi|)<=10000001<=|T|<=10000

COJ 1010 WZJ的数据结构(十) 线段树的地狱

传送门:http://oj.cnuschool.org.cn/oj/home/problem.htm?problemID=1001 WZJ的数据结构(十) 难度级别:D: 运行时间限制:3000ms: 运行空间限制:51200KB: 代码长度限制:2000000B 试题描述 请你设计一个数据结构,高效执行以下过程: #include<iostream>using namespace std;const int maxn=100010;int A[maxn];int tp,ql,qr,v;int