我先用费用流的方法去跑spfa,然后完美T掉6个点。
就说正解吧,正解是跑两次spfa,然后就可以找出最短路覆盖的边(详细过程请看代码rebuild())。然后建图跑最大流
Code
1 #include <iostream> 2 #include <cstdio> 3 #include <ctime> 4 #include <cmath> 5 #include <cctype> 6 #include <cstring> 7 #include <cstdlib> 8 #include <fstream> 9 #include <sstream> 10 #include <algorithm> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <vector> 16 #include <stack> 17 #ifndef WIN32 18 #define Auto "%lld" 19 #else 20 #define Auto "%I64d" 21 #endif 22 using namespace std; 23 typedef bool boolean; 24 const signed int inf = (signed)((1u << 31) - 1); 25 const double eps = 1e-6; 26 const int binary_limit = 128; 27 #define smin(a, b) a = min(a, b) 28 #define smax(a, b) a = max(a, b) 29 #define max3(a, b, c) max(a, max(b, c)) 30 #define min3(a, b, c) min(a, min(b, c)) 31 template<typename T> 32 inline boolean readInteger(T& u){ 33 char x; 34 int aFlag = 1; 35 while(!isdigit((x = getchar())) && x != '-' && x != -1); 36 if(x == -1) { 37 ungetc(x, stdin); 38 return false; 39 } 40 if(x == '-'){ 41 x = getchar(); 42 aFlag = -1; 43 } 44 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 45 ungetc(x, stdin); 46 u *= aFlag; 47 return true; 48 } 49 50 typedef class Edge { 51 public: 52 int end; 53 int next; 54 int flow; 55 int cap; 56 int lvl; 57 Edge(int end = 0, int next = -1, int flow = 0, int cap = 0, int lvl = 0):end(end), next(next), flow(flow), cap(cap), lvl(lvl) { } 58 }Edge; 59 60 typedef class MapManager { 61 public: 62 int ce; 63 vector<Edge> edge; 64 int* h; 65 66 MapManager():ce(0), h(NULL) { } 67 MapManager(int nodes):ce(0) { 68 h = new int[(const int)(nodes + 1)]; 69 memset(h, -1, sizeof(int) * (nodes + 1)); 70 } 71 72 inline void addEdge(int from, int end, int flow, int cap, int lvl) { 73 edge.push_back(Edge(end, h[from], flow, cap, lvl)); 74 h[from] = ce++; 75 } 76 77 inline void addDoubleEdge(int from, int end, int cap, int lvl) { 78 if(cap == 0) return; 79 addEdge(from, end, 0, cap, lvl); 80 addEdge(end, from, cap, cap, lvl); 81 } 82 83 Edge& operator [] (int pos) { 84 return edge[pos]; 85 } 86 }MapManager; 87 #define m_begin(g, i) (g).h[(i)] 88 #define m_endpos -1 89 90 #define LL long long 91 92 int n, m; 93 int s, t; 94 MapManager g; 95 96 inline void init() { 97 readInteger(n); 98 readInteger(m); 99 g = MapManager(n + 1); 100 s = 1, t = n; 101 for(int i = 1, a, b, c; i <= m; i++) { 102 readInteger(a); 103 readInteger(b); 104 readInteger(c); 105 g.addDoubleEdge(a, b, 1, c); 106 } 107 } 108 109 queue<int> que; 110 boolean* vis; 111 LL *f; 112 LL *f1; 113 inline void init_spfa() { 114 vis = new boolean[t + 1]; 115 f = new LL[t + 1]; 116 f1 = new LL[t + 1]; 117 } 118 119 inline void spfa(int s, int t, LL* &f2, boolean sign) { 120 memset(vis, false, sizeof(boolean) * (n + 1)); 121 memset(f2, 0x7f, sizeof(long long) * (n + 1)); 122 f2[s] = 0; 123 que.push(s); 124 while(!que.empty()) { 125 int e = que.front(); 126 que.pop(); 127 vis[e] = false; 128 for(int i = m_begin(g, e); i != m_endpos; i = g[i].next) { 129 int& eu = g[i].end; 130 if(g[i].flow ^ sign) continue; 131 if(f2[eu] > f2[e] + g[i].lvl) { 132 f2[eu] = f2[e] + g[i].lvl; 133 if(!vis[eu] && eu != t) { 134 vis[eu] = true; 135 que.push(eu); 136 } 137 } 138 } 139 } 140 } 141 142 boolean* onpath; 143 MapManager rg; 144 inline void rebuild() { 145 rg = MapManager(t); 146 onpath = new boolean[(t + 1)]; 147 memset(onpath, false, sizeof(boolean) * (t + 1)); 148 for(int i = 1; i <= n; i++) 149 if(f[i] + f1[i] == f[t]) 150 onpath[i] = true; 151 for(int i = s; i <= t; i++) { 152 if(!onpath[i]) continue; 153 for(int j = m_begin(g, i); j != m_endpos; j = g[j].next) { 154 int& e = g[j].end; 155 if(onpath[e] && g[j].flow == 0 && f[i] + g[j].lvl == f[e]) 156 rg.addDoubleEdge(i, e, 1, 0); //,printf("%d->%d ", i, e); 157 } 158 } 159 } 160 161 int *divs; 162 inline boolean bfs() { 163 memset(divs, -1, sizeof(int) * (t + 1)); 164 que.push(s); 165 divs[s] = 0; 166 while(!que.empty()) { 167 int e = que.front(); 168 que.pop(); 169 for(int i = m_begin(rg, e); i != m_endpos; i = rg[i].next) { 170 int& eu = rg[i].end; 171 if(divs[eu] != -1 || rg[i].cap == rg[i].flow) continue; 172 divs[eu] = divs[e] + 1; 173 que.push(eu); 174 } 175 } 176 return divs[t] != -1; 177 } 178 179 int *cur; 180 int blockedflow(int node, int minf) { 181 if(node == t || minf == 0) return minf; 182 int f, flow = 0; 183 for(int& i = cur[node]; i != m_endpos; i = rg[i].next) { 184 int& e = rg[i].end; 185 if(divs[e] == divs[node] + 1 && (f = blockedflow(e, min(minf, rg[i].cap - rg[i].flow))) > 0) { 186 rg[i].flow += f; 187 rg[i ^ 1].flow -= f; 188 flow += f; 189 minf -= f; 190 if(minf == 0) return flow; 191 } 192 } 193 return flow; 194 } 195 196 inline int dinic() { 197 divs = new int[(t + 1)]; 198 cur = new int[(t + 1)]; 199 int maxflow = 0; 200 while(bfs()) { 201 for(int i = s; i <= t; i++) 202 cur[i] = m_begin(rg, i); 203 maxflow += blockedflow(s, inf); 204 } 205 return maxflow; 206 } 207 208 inline void solve() { 209 printf("%d", dinic()); 210 } 211 212 int main() { 213 freopen("change.in", "r", stdin); 214 freopen("change.out", "w", stdout); 215 init(); 216 init_spfa(); 217 spfa(s, t, f, false); 218 spfa(t, s, f1, true); 219 rebuild(); 220 solve(); 221 return 0; 222 }
二分答案,然后奇、偶数分开分别连源点和汇点,两者加起来是素数就加一条边。特殊处理1,只保留一个。
Code
1 #include <iostream> 2 #include <cstdio> 3 #include <ctime> 4 #include <cmath> 5 #include <cctype> 6 #include <cstring> 7 #include <cstdlib> 8 #include <fstream> 9 #include <sstream> 10 #include <algorithm> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <vector> 16 #include <stack> 17 #ifndef WIN32 18 #define Auto "%lld" 19 #else 20 #define Auto "%I64d" 21 #endif 22 using namespace std; 23 typedef bool boolean; 24 const signed int inf = (signed)((1u << 31) - 1); 25 const double eps = 1e-6; 26 const int binary_limit = 128; 27 #define smin(a, b) a = min(a, b) 28 #define smax(a, b) a = max(a, b) 29 #define max3(a, b, c) max(a, max(b, c)) 30 #define min3(a, b, c) min(a, min(b, c)) 31 template<typename T> 32 inline boolean readInteger(T& u){ 33 char x; 34 int aFlag = 1; 35 while(!isdigit((x = getchar())) && x != '-' && x != -1); 36 if(x == -1) { 37 ungetc(x, stdin); 38 return false; 39 } 40 if(x == '-'){ 41 x = getchar(); 42 aFlag = -1; 43 } 44 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 45 ungetc(x, stdin); 46 u *= aFlag; 47 return true; 48 } 49 50 typedef class Edge { 51 public: 52 int end; 53 int next; 54 int flow; 55 int cap; 56 int lvl; 57 Edge(int end = 0, int next = -1, int flow = 0, int cap = 0, int lvl = 0):end(end), next(next), flow(flow), cap(cap), lvl(lvl) { } 58 }Edge; 59 60 typedef class MapManager { 61 public: 62 int ce; 63 vector<Edge> edge; 64 int* h; 65 66 MapManager():ce(0), h(NULL) { } 67 MapManager(int nodes):ce(0) { 68 h = new int[(const int)(nodes + 1)]; 69 memset(h, -1, sizeof(int) * (nodes + 1)); 70 } 71 72 inline void addEdge(int from, int end, int flow, int cap, int lvl) { 73 edge.push_back(Edge(end, h[from], flow, cap, lvl)); 74 h[from] = ce++; 75 } 76 77 inline void addDoubleEdge(int from, int end, int cap, int lvl) { 78 if(cap == 0) return; 79 // printf("%d -> %d (with the capt %d) ", from, end, cap); 80 addEdge(from, end, 0, cap, lvl); 81 addEdge(end, from, cap, cap, lvl); 82 } 83 84 Edge& operator [] (int pos) { 85 return edge[pos]; 86 } 87 88 inline void clear() { 89 edge.clear(); 90 delete[] h; 91 } 92 }MapManager; 93 #define m_begin(g, i) (g).h[(i)] 94 #define m_endpos -1 95 96 int n, m; 97 int s, t; 98 int *fs, *ts, *ls; 99 100 inline void init() { 101 readInteger(n); 102 readInteger(m); 103 s = 0, t = n + 1; 104 fs = new int[(n + 1)]; 105 ts = new int[(n + 1)]; 106 ls = new int[(n + 1)]; 107 int sum = 0; 108 for(int i = 1; i <= n; i++) { 109 readInteger(fs[i]); 110 readInteger(ts[i]); 111 readInteger(ls[i]); 112 sum += fs[i]; 113 } 114 if(sum < m) { 115 puts("-1"); 116 exit(0); 117 } 118 } 119 120 int num = 0; 121 const int limit = 2e7; 122 int prime[1270608]; 123 boolean *vis; 124 inline void Euler() { 125 vis = new boolean[limit + 1]; 126 memset(vis, false, sizeof(boolean) * (limit + 1)); 127 for(int i = 2; i <= limit; i++) { 128 if(!vis[i]) prime[num++] = i; 129 for(int j = 0; j < num; j++) { 130 int x = i * 1LL * prime[j]; 131 if(x > limit) break; 132 vis[x] = true; 133 if((i % prime[j]) == 0) break; 134 } 135 } 136 } 137 138 inline void init_map(MapManager& g, int mid, int& sum) { 139 g = MapManager(t); 140 int maxonef = 0, maxid = -1; 141 for(int i = 1; i <= n; i++) 142 if(ls[i] <= mid && ts[i] == 1 && fs[i] > maxonef) 143 maxonef = fs[i], maxid = i; 144 for(int i = 1; i <= n; i++) { 145 if(((ts[i] == 1 && i == maxid) || (ts[i] != 1 && (ts[i] & 1) == 1)) && ls[i] <= mid) 146 g.addDoubleEdge(s, i, fs[i], ls[i]), sum += fs[i]; 147 else if((ts[i] & 1) == 0 && ls[i] <= mid) 148 g.addDoubleEdge(i, t, fs[i], ls[i]), sum += fs[i]; 149 } 150 for(int i = 1; i <= n; i++) { 151 if(!(ts[i] & 1)) continue; 152 for(int j = 1; j <= n; j++) { 153 if(!vis[ts[i] + ts[j]]) { 154 g.addDoubleEdge(i, j, inf, 0); 155 } 156 } 157 } 158 } 159 160 int* dep; 161 queue<int> que; 162 MapManager g; 163 inline boolean bfs(int mid) { 164 memset(dep, -1, sizeof(int) * (t + 1)); 165 dep[s] = 0; 166 que.push(s); 167 while(!que.empty()) { 168 int e = que.front(); 169 que.pop(); 170 for(int i = m_begin(g, e); i != m_endpos; i = g[i].next) { 171 int& eu = g[i].end; 172 if(dep[eu] != -1) continue; 173 if(g[i].lvl > mid) continue; 174 if(g[i].cap == g[i].flow) continue; 175 dep[eu] = dep[e] + 1; 176 que.push(eu); 177 } 178 } 179 return dep[t] != -1; 180 } 181 182 int* cur; 183 int blockedflow(int node, int minf, int mid) { 184 if(node == t || minf == 0) return minf; 185 // cout << node << endl; 186 int f, flow = 0; 187 for(int& i = cur[node]; i != m_endpos; i = g[i].next) { 188 int& e = g[i].end; 189 if(g[i].lvl <= mid && dep[e] == dep[node] + 1 && (f = blockedflow(e, min(minf, g[i].cap - g[i].flow), mid)) > 0) { 190 g[i].flow += f; 191 g[i ^ 1].flow -= f; 192 flow += f; 193 minf -= f; 194 if(minf == 0) return flow; 195 } 196 } 197 return flow; 198 } 199 200 inline void init_dinic() { 201 dep = new int[(t + 1)]; 202 cur = new int[(t + 1)]; 203 } 204 205 int dinic(int mid) { 206 int sum = 0, maxflow = 0; 207 init_map(g, mid, sum); 208 while(bfs(mid)) { 209 for(int i = s; i <= t; i++) 210 cur[i] = m_begin(g, i); 211 maxflow += blockedflow(s, inf, mid); 212 } 213 g.clear(); 214 // cout << maxflow << endl; 215 return sum - maxflow; 216 } 217 218 inline void solve() { 219 int l = 1, r = (1e9) + 1; 220 while(l <= r) { 221 int mid = (l + r) >> 1; 222 if(dinic(mid) >= m) r = mid - 1; 223 else l = mid + 1; 224 } 225 if(r == (1e9) + 1) puts("-1"); 226 else printf("%d ", r + 1); 227 } 228 229 int main() { 230 freopen("card.in", "r", stdin); 231 freopen("card.out", "w", stdout); 232 Euler(); 233 init(); 234 init_dinic(); 235 solve(); 236 return 0; 237 }
先Tarjan弄一发,然后开始spfa,转移的时候判一下起点和终点是否在同一强连通分量内。
Code
1 #include <iostream> 2 #include <cstdio> 3 #include <ctime> 4 #include <cmath> 5 #include <cctype> 6 #include <cstring> 7 #include <cstdlib> 8 #include <fstream> 9 #include <sstream> 10 #include <algorithm> 11 #include <map> 12 #include <set> 13 #include <stack> 14 #include <queue> 15 #include <vector> 16 #include <stack> 17 #ifndef WIN32 18 #define Auto "%lld" 19 #else 20 #define Auto "%I64d" 21 #endif 22 using namespace std; 23 typedef bool boolean; 24 const signed int inf = (signed)((1u << 31) - 1); 25 const signed long long llf = (signed long long)((1ull << 61) - 1); 26 const double eps = 1e-6; 27 const int binary_limit = 128; 28 #define smin(a, b) a = min(a, b) 29 #define smax(a, b) a = max(a, b) 30 #define max3(a, b, c) max(a, max(b, c)) 31 #define min3(a, b, c) min(a, min(b, c)) 32 template<typename T> 33 inline boolean readInteger(T& u){ 34 char x; 35 int aFlag = 1; 36 while(!isdigit((x = getchar())) && x != '-' && x != -1); 37 if(x == -1) { 38 ungetc(x, stdin); 39 return false; 40 } 41 if(x == '-'){ 42 x = getchar(); 43 aFlag = -1; 44 } 45 for(u = x - '0'; isdigit((x = getchar())); u = (u << 1) + (u << 3) + x - '0'); 46 ungetc(x, stdin); 47 u *= aFlag; 48 return true; 49 } 50 51 ///map template starts 52 typedef class Edge{ 53 public: 54 int end; 55 int next; 56 int w; 57 Edge(const int end = 0, const int next = 0, const int w = 0):end(end), next(next), w(w){} 58 }Edge; 59 60 typedef class MapManager{ 61 public: 62 int ce; 63 int *h; 64 Edge *edge; 65 MapManager(){} 66 MapManager(int points, int limit):ce(0){ 67 h = new int[(const int)(points + 1)]; 68 edge = new Edge[(const int)(limit + 1)]; 69 memset(h, 0, sizeof(int) * (points + 1)); 70 } 71 inline void addEdge(int from, int end, int w){ 72 edge[++ce] = Edge(end, h[from], w); 73 h[from] = ce; 74 } 75 inline void addDoubleEdge(int from, int end, int w){ 76 addEdge(from, end, w); 77 addEdge(end, from, w); 78 } 79 Edge& operator [] (int pos) { 80 return edge[pos]; 81 } 82 }MapManager; 83 #define m_begin(g, i) (g).h[(i)] 84 ///map template ends 85 86 #define LL long long 87 88 typedef class Data { 89 public: 90 LL mag; 91 LL dis; 92 93 Data(LL mag = llf, LL dis = llf):mag(mag), dis(dis) { } 94 95 boolean operator < (Data b) const { 96 if(mag != b.mag) return mag < b.mag; 97 return dis < b.dis; 98 } 99 100 Data operator + (Data b) { 101 return Data(mag + b.mag, dis + b.dis); 102 } 103 }Data; 104 105 int n, m; 106 MapManager g; 107 MapManager rg; 108 109 inline void init() { 110 readInteger(n); 111 readInteger(m); 112 g = MapManager(n, m); 113 rg = MapManager(n, m); 114 for(int i = 1, a, b, c; i <= m; i++) { 115 readInteger(a); 116 readInteger(b); 117 readInteger(c); 118 g.addEdge(a, b, c); 119 rg.addEdge(b, a, c); 120 } 121 } 122 123 int cnt = 0, scc = 0; 124 int* visitID; 125 int* exitID; 126 boolean* visited; 127 boolean* instack; 128 stack<int> s; 129 int *belong; 130 inline void init_tarjan() { 131 int an = n + 1; 132 visitID = new int[(an)]; 133 exitID = new int[(an)]; 134 visited = new boolean[(an)]; 135 instack = new boolean[(an)]; 136 belong = new int[(an)]; 137 memset(visited, false, sizeof(boolean) * an); 138 memset(instack, false, sizeof(boolean) * an); 139 memset(belong, 0, sizeof(int) * an); 140 } 141 142 void tarjan(int node) { 143 visitID[node] = exitID[node] = cnt++; 144 visited[node] = instack[node] = true; 145 s.push(node); 146 147 for(int i = m_begin(g, node); i; i = g[i].next) { 148 int& e = g[i].end; 149 if(!visited[e]) { 150 tarjan(e); 151 smin(exitID[node], exitID[e]); 152 } else if(instack[e]) { 153 smin(exitID[node], visitID[e]); 154 } 155 } 156 157 if(visitID[node] == exitID[node]) { 158 int now = -1; 159 scc++; 160 while(now != node) { 161 now = s.top(); 162 s.pop(); 163 instack[now] = false; 164 belong[now] = scc; 165 } 166 } 167 } 168 169 deque<int> que; 170 Data *f; 171 boolean *vis; 172 inline void spfa(int s) { 173 f = new Data[n + 1]; 174 vis = new boolean[n + 1]; 175 memset(vis, false, sizeof(boolean) * (n + 1)); 176 que.push_front(s); 177 f[s] = Data(0, 0); 178 while(!que.empty()) { 179 int e = que.front(); 180 que.pop_front(); 181 vis[e] = false; 182 for(int i = m_begin(rg, e); i; i = rg[i].next) { 183 int& eu = rg[i].end; 184 Data w((belong[e] == belong[eu]) ? (1) : (0), rg[i].w); 185 if(f[e] + w < f[eu]) { 186 f[eu] = f[e] + w; 187 if(!vis[eu]) { 188 vis[eu] = true; 189 if(!que.empty() && f[eu] < f[que.front()]) 190 que.push_front(eu); 191 else 192 que.push_back(eu); 193 } 194 } 195 } 196 } 197 } 198 199 inline void solve() { 200 for(int i = 2; i <= n; i++) { 201 if(f[i].mag == llf) 202 puts("-1"); 203 else 204 printf(Auto" "Auto" ", f[i].mag, f[i].dis); 205 } 206 } 207 208 int main() { 209 freopen("festival.in", "r", stdin); 210 freopen("festival.out", "w", stdout); 211 init(); 212 init_tarjan(); 213 for(int i = 1; i <= n; i++) 214 if(!visited[i]) 215 tarjan(i); 216 spfa(1); 217 solve(); 218 return 0; 219 }