We should have done this seriously, and the ideas are correct.
Question C: The number of knives cannot be met after the cross-cutting or vertical-cutting is completed, and then the cross-cutting and vertical-cutting (vertical cutting + cross-cutting) are considered ),
Because cross-cutting + vertical-cutting (or vertical-cutting + cross-cutting) will generate the number of parts to be cut, so that the smallest part will not be as large as possible.
The Code is as follows. Although it is relatively long and messy, it can be compressed into several lines. Because there are almost four small pieces of repeated code, you are too lazy to compress it.
Note that, for example, when determining the minimum block, for example, the nine rows should be divided into two parts. The minimum remaining part is not 9 modulo 2, but 4.
M/(k + 1) <= m-m/(k + 1) * k
#include<bits/stdc++.h>using namespace std;typedef long long LL;const int MAX = 1e6+10;const LL MOD = 1e9+7;LL f[1000];int main() { LL n,m,k; //freopen("in.txt", "r", stdin); while(scanf("%I64d %I64d %I64d",&n,&m, &k)==3) { if(k > (n+m-2)) { printf("-1\n"); continue;} LL k1 = k; LL ans = 0, ans2 = 0; if(1){ if(k<=(m-1)){ if(m%(k+1)==0) ans = m/(k+1)*n; else if(m/(k+1)<=m-m/(k+1)*k) { ans = m/(k+1)*n; } else ans = (m/(k+1)-1)*n; } else { k -= (m-1); if(n%(k+1)==0) ans = n/(k+1); else if(m/(k+1)<=m-m/(k+1)*k) { ans = n/(k+1); } else ans = (n/(k+1)-1); } } //printf("%I64d~\n", ans); swap(n, m); if(2){ k = k1; if(k<=(m-1)){ if(m%(k+1)==0) { ans2 = m/(k+1)*n; } else if(m/(k+1)<=m-m/(k+1)*k) { ans2 = m/(k+1)*n; } else ans2 = (m/(k+1)-1)*n; } else { k -= (m-1); if(n%(k+1)==0) ans2 = n/(k+1); else if(m/(k+1)<=m-m/(k+1)*k) { ans2 = n/(k+1); } else ans2 = (n/(k+1)-1); } } printf("%I64d\n", max(ans, ans2)); }}
Question d
I am very excited when I look at the question. It is very interesting in graph theory.
The idea at the beginning is wrong. Each time you perform a relaxation operation, you can determine whether the current side has been marked, and then perform the subtraction operation. In this way, you may forget to make some updates later, overwrite the previous tag
Correct thinking:
When each time the priority team lists the points, determine the number of the shortest paths from the start point to the point is repeated with K (train route ).
Note the following:
1. How to record the maximum number of short circuits
2. Processing When k = count [u]
3. Small details: the first node u, TT and count [u] are both equal to 0.
The code is still quite fast ~
# 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 0x3c3c3ctypedef long ll; const int maxn = 4*1e5; bool vis [Max N]; struct edge {int from, to, DIST, CNT ;}; struct node {int D, U; bool operator <(const node & A) const {return. d <D; // sort data in ascending order. }; Int n, m, K; // number of points and number of edges, represented by N. E cannot conflict with M. Vector <edge> edges; // edge list vector <int> G [maxn]; // Edge Number (starting from 0) starting from each node vector <int> QW [maxn]; int count [maxn]; bool done [maxn]; // whether int d [maxn] has been permanently numbered; // The distance from int P [maxn] to each point in S; // void Init () {for (INT I = 0; I <n; I ++) g [I]. clear (); // clear the edges. clear ();} void addedge (int from, int to, int Dist) // if there is no direction, the addedge {edges must be called twice for each undirected edge. push_back (edge) {from, to, DIST}); int temp = edges. size (); G [from]. push_back (temp-1);} void Dijk (INT s) {CLR (count); priority_queue <node> q; For (INT I = 0; I <n; I ++) d [I] = inf; d [s] = 0; memset (done, 0, sizeof (done); q. push (node) {0, s}); While (! Q. empty () {node x = Q. top (); q. pop (); int u = x. u; If (done [u]) continue; done [u] = true; For (INT I = 0; I <G [u]. size (); I ++) {edge & E = edges [G [u] [I]; If (d [E. to]> d [u] + E. dist) {d [E. to] = d [u] + E. dist; P [E. to] = G [u] [I]; q. push (node) {d [E. to], E. to}); count [E. to] = 1;} else if (d [E. to] = d [u] + E. dist) {count [E. to] ++ ;}} int TT = 0; For (INT I = 0; I <QW [u]. size (); I ++) {If (QW [u] [I]> d [u]) {// printf ("% d ~ \ N ", U, QW [u] [I], d [u]); int temp = k-1; k = temp ;} else if (QW [u] [I] = d [u]) TT ++;} // printf ("% d! \ N ", U, TT, Count [u]); If (TT = 0) continue; else if (TT <count [u]) {k-= tt ;} else if (TT = count [u]) K-= (TT-1) ;}} int main () {// FP1; while (scanf ("% d", & N, & M, & K) = 3) {int k1 = K; Init (); int U, v, W; For (INT I = 1; I <= m; I ++) {scanf ("% d", & U, & V, & W); U --; V --; addedge (U, V, W); addedge (v, U, W) ;}for (INT I = m + 1; I <= m + k; I ++) {scanf ("% d", & U, & V); U --; addedge (0, U, V ); addedge (u, 0, V); QW [u]. pb (V);} Dijk (0); printf ("% d \ n", K1-k);} return 0 ;}