1、拓扑排序,要求输出小的数尽量靠前,而不是字典序
可采用逆序拓扑方法。 (好多方法倒着来就是一片新天地...
自己以前做过的题肿么可以又跪!
2、分块方法
具体便是每次更新x结点,只更新与x结点相邻的点并且点的度数比x大的。
比x结点度数大的点不超过 sqrt(2m)
(其实想想还是蛮显然的 比如结点x要有m度,若与x相邻的点的度数都比x大,度数为m+1度,则为m+1度的这些点会有m+1条边,((m+1)*m-m)即为结果
附个代码
#include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> using namespace std; #define clr(x) memset(x,0,sizeof(x)) #define fp1 freopen("in.txt","r",stdin) #define fp2 freopen("out.txt","w",stdout) #define pb push_back #define INF 0x3c3c3c3c typedef long long LL; const int maxn = 1e5+200; int deg[maxn]; vector<int> G[maxn]; int w[maxn], sum[maxn], num[maxn]; typedef struct edge{ int x, y; }edge; int main() { // fp1; edge Edge[maxn]; int T, n, m, u, v; scanf("%d", &T); while(T--){ scanf("%d %d", &n, &m); clr(deg); clr(w); clr(sum); for(int i = 0;i < maxn;i++) G[i].clear(); for(int i = 1;i <= m;i++){ scanf("%d %d", &Edge[i].x, &Edge[i].y); deg[Edge[i].x]++; deg[Edge[i].y]++; } for(int i = 1;i <= m;i++){ if(deg[Edge[i].x] < deg[Edge[i].y]) { G[Edge[i].x].pb(Edge[i].y); } else G[Edge[i].y].pb(Edge[i].x); } int q, op; scanf("%d", &q); while(q--){ scanf("%d", &op); if(op == 0){ scanf("%d %d", &u, &v); w[u] += v; for(int i = 0;i < G[u].size();i++){ sum[G[u][i]] += v; //printf("~%d %d\n", u, G[u][i]); } } else { scanf("%d", &u); int ans = sum[u]; for(int i = 0;i < G[u].size();i++){ ans += w[G[u][i]]; } printf("%d\n", ans); } } } return 0; }
3、网络流?
ps: 我感受到了来自自己内心深处的囧状....
bestcoder round #1,布布扣,bubuko.com
原文:http://blog.csdn.net/cgf1993/article/details/38009977