Problem 1. Tree
Input file: tree.inOutput file: tree.outTime limit: 1 second给出 N 个点的树和 K,问能否把树划分成 N /K 个连通块,且每个连通块的点数都是 K。Input第 1 行,1 个整数 T ,表示数据组数。接下来 T 组数据,对于每组数据:第 1 行,2 个整数 N, K。接下来 (N − 1) 行,每行 2 个整数 Ai , Bi ,表示边 (Ai , Bi )。点用 1, 2, . . . , N 编号。Output对于每组数据,输出 YES或 NO。题解:这个题很水,只是当时没想到而已!~~~
实际上我们把整棵树划分出来仅需要暴搜就好了~~~2333
我们从叶子节点向上回溯,叶子节点是1,其父亲的值就是各子节点的和,以此类推,回溯上去,一旦超过k显然就是无解了~等于k的话我们就归零重新计数。
代码:by nevermore
1 #include2 #include 3 #include 4 using namespace std; 5 #define MAXN 100100 6 struct Link 7 { 8 int to, next; 9 }l[MAXN * 2];10 int first[MAXN];11 int add = 0;12 void add_edge(int u, int v)13 {14 l[add].to = v;15 l[add].next = first[u];16 first[u] = add ++;17 }18 int T, n, k;19 int num[MAXN];20 int temp = 0;21 bool use[MAXN];22 bool dfs(int x)23 {24 use[x] = 1;25 for (int i = first[x]; ~ i; i = l[i].next)26 {27 if (!use[l[i].to])28 {29 if (dfs(l[i].to))30 num[x] += num[l[i].to];31 else return false;32 }33 }34 if (num[x] == k) num[x] -= k;35 else if (num[x] > k) return false;36 return true;37 }38 int main()39 {40 freopen("tree.in", "r", stdin); freopen("tree.out", "w", stdout);41 scanf("%d", &T);42 while (T --)43 {44 memset(use, 0, sizeof(use));45 add = 0;46 scanf("%d%d", &n, &k);47 int u, v;48 memset(first, -1, sizeof(first));49 for (int i = 1; i < n; i ++)50 {51 scanf("%d%d", &u, &v);52 add_edge(u, v);53 add_edge(v, u);54 }55 for (int i = 1; i <= n; i ++) num[i] = 1;56 if (dfs(1) && n % k == 0) printf("YES\n");57 else printf("NO\n");58 for (int i = 0; i < add; i ++)59 l[i].to = l[i].next = 0;60 }61 return 0;62 }
Problem 2. Graph
给出 N 个点,M 条边的有向图,对于每个点 v,求 A(v) 表示从点 v 出发,能到达的编号最大的点。
Input第 1 行,2 个整数 N, M 。接下来 M 行,每行 2 个整数 Ui, Vi ,表示边 ⟨Ui, Vi⟩。点用 1, 2, . . . , N 编号。OutputN 个整数 A(1), A(2), . . . , A(N )。 Note
• 对于 60% 的数据,1 ≤ N, K ≤ 10^3;
• 对于 100% 的数据,1 ≤ N, M ≤ 10^5。
正解:反向建图,从编号大的点往回跑bfs,更新每个点所能连到的最大编号。
代码:还是nevermore的,谁让他写好了呢?2333我不是代码的生成者,我只做代码的搬运工
1 #include2 3 #include 4 5 #include 6 7 #include 8 9 using namespace std; 10 11 12 13 14 #define MAXN 100100 15 16 17 18 19 struct Link 20 21 { 22 23 int to, next; 24 25 }l[MAXN]; 26 27 int first[MAXN]; 28 29 30 31 32 int add = 0; 33 34 void add_edge(int u, int v) 35 36 { 37 38 l[add].to = v; 39 40 l[add].next = first[u]; 41 42 first[u] = add ++; 43 44 } 45 46 47 48 49 int n, m; 50 51 int ans[MAXN]; 52 53 54 55 56 queue q; 57 58 bool use[MAXN]; 59 60 61 62 63 void bfs(int s) 64 65 { 66 67 q.push(s); 68 69 use[s] = 1; 70 71 while (!q.empty()) 72 73 { 74 75 int x = q.front(); 76 77 q.pop(); 78 79 for (int i = first[x]; ~ i; i = l[i].next) 80 81 if (!use[l[i].to]) 82 83 { 84 85 ans[l[i].to] = max(ans[l[i].to], ans[x]); 86 87 use[l[i].to] = 1; 88 89 q.push(l[i].to); 90 91 } 92 93 } 94 95 } 96 97 98 99 100 int main()101 102 {103 104 freopen("graph.in", "r", stdin);105 106 freopen("graph.out", "w", stdout);107 108 scanf("%d%d", &n, &m);109 110 int u, v;111 112 memset(first, -1, sizeof(first));113 114 for (int i = 1; i <= m; i ++)115 116 {117 118 scanf("%d%d", &u, &v);119 120 add_edge(v, u);121 122 }123 124 for (int i = 1; i <= n; i ++) ans[i] = i;125 126 for (int i = n; i >= 1; i --)127 128 if (ans[i] == i)129 130 bfs(i);131 132 for (int i = 1; i <= n; i ++)133 134 printf("%d ", ans[i]);135 136 return 0;137 }
in fact 我自己的思路和这个一点都不一样,我自己的思想是借鉴的最短路算法,我们每次只需要计原来的总边权为路径上最大的编号,三角不等式更新的时候只需要取max记好了。
唉(此处是二声)~这些好像我都写过。。。。。2333具体代码参见之前的随笔“最大路”,改改,那里是最大的边的权值,改成标号就好了~~更简单了不是么?
第三题必有蹊跷。。。。