Regionals 2012 :: Asia - Jakarta
UVA地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&category=559
A。搜索就行了,水题。
#define N 55 int a[N][N] ; int n , m ; bool vis[N][N] ; int inmap(int x ,int y){ if(x >= 0 && x < n && y >= 0 && y < m)return 1 ;return 0 ; } int mx[4] = {0 , 0, 1 , -1} ; int my[4] = {1 , -1, 0 , 0} ; int ans = 0 ; void dfs(int x , int y){ int fk = 0 ; for (int i = 0 ; i < 4; i ++ ){ int tx = x + mx[i] ; int ty = y + my[i] ; if(inmap(tx ,ty) && a[x][y] > a[tx][ty]){ vis[tx][ty] = 1 ; dfs(tx , ty) ; vis[tx][ty] = 0 ; fk ++ ; } } if(!fk)ans ++ ; } int main() { int T ; cin >> T ; int ca = 0 ; while(T -- ){ cin >> n >> m ; for (int i = 0 ; i < n ; i ++ ){ for (int j = 0 ; j < m ; j ++ )cin >> a[i][j] ; } ans = 0 ; for (int i = 0 ; i < n ; i ++ ){ for (int j = 0 ; j < m ; j ++ ){ int snum = 0 ; int hnum = 0 ; mem(vis ,0) ; for (int k = 0 ; k < 4 ; k ++ ){ int tx = i + mx[k] ; int ty = j + my[k] ; if(inmap(tx , ty)){ snum ++ ; if(a[i][j] >= a[tx][ty])hnum ++ ; } } vis[i][j] = 1 ; if(snum == hnum)dfs(i , j) ; } } printf("Case #%d: %d\n",++ ca , ans) ; } return 0 ; }
B,
首先我们假设这个点从父节点过来的流量是x ,那么这个流量肯定是要流向其他点的。
那么是哪些点呢,我们要具体判断一下,首先我们找出出父节点过来边的其他流量的总和,和最大流量。
然后对于这个最大流量,我们要判断一下,一开始我就只这里没判断导致WA了,这里要判断最大流量是否大于剩余的流量,如果是的话,那么我们就可以将父节点的流量全部流进这里,然后从这里流出最大流量-父节点流量,那么答案就加上这个流量即可。
如果小于的话,那么我们只要判断父节点的流量是否大于剩余的总流量,如果大于,那么无所谓,答案就不加,因为父节点的流量可以流满所有的点,如果小于,我们只要把这个流量减去父节点的流量,然后将剩余流量两两配对即可,即x / 2 + x % 2 。
这样就很清楚了,一个DFS就可以了。
#include <set> #include <map> #include <stack> #include <cmath> #include <queue> #include <cstdio> #include <string> #include <vector> #include <iomanip> #include <cstring> #include <iostream> #include <algorithm> #define Max 2505 #define FI first #define SE second #define ll long long #define PI acos(-1.0) #define inf 0x3fffffff #define LL(x) ( x << 1 ) #define bug puts("here") #define PII pair<int,int> #define RR(x) ( x << 1 | 1 ) #define mp(a,b) make_pair(a,b) #define mem(a,b) memset(a,b,sizeof(a)) #define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i ) using namespace std; inline void RD(int &ret) { char c; int flag = 1 ; do { c = getchar(); if(c == '-')flag = -1 ; } while(c < '0' || c > '9') ; ret = c - '0'; while((c=getchar()) >= '0' && c <= '9') ret = ret * 10 + ( c - '0' ); ret *= flag ; } inline void OT(int a) { if(a >= 10)OT(a / 10) ; putchar(a % 10 + '0') ; } inline void RD(double &ret) { char c ; int flag = 1 ; do { c = getchar() ; if(c == '-')flag = -1 ; } while(c < '0' || c > '9') ; ll n1 = c - '0' ; while((c = getchar()) >= '0' && c <= '9') { n1 = n1 * 10 + c - '0' ; } ll n2 = 1 ; while((c = getchar()) >= '0' && c <= '9') { n1 = n1 * 10 + c - '0' ; n2 *= 10 ; } ret = flag * (double)n1 / (double)(n2) ; } /*********************************************/ #define N 1111111 int n ; struct kdq { int s , e, l, next ; } ed[N] ; int head[N] , num ; void init() { mem(head, -1) ; num = 0 ; } void add(int s ,int e ,int l) { ed[num].s = s ; ed[num].e = e ; ed[num].l = l ; ed[num].next = head[s] ; head[s] = num ++ ; } bool vis[N] ; int x[N] ; int in[N] ; int ans = 0 ; void dfs(int now ,int fa ,int pre){ int sum = 0 ; int MX = 0 ; int pos = 0 ; for (int i = head[now] ; ~i ; i = ed[i].next ){ int e = ed[i].e ; int l = ed[i].l ; if(e == fa)continue ; dfs(e , now , l) ; sum += l ; if(MX < l){ MX = l ; pos = e ; } } if(MX > sum - MX + pre )ans += MX - pre ; else if(sum >= pre)ans += (sum - pre ) / 2 + (sum - pre) % 2 ; } int main() { int T ; cin >> T ; int ca = 0 ; while (T -- ) { cin >> n ; init() ; mem(in, 0) ; mem(vis ,0) ; int a , b , c ; int dd = 0 ; for (int i = 0 ; i < n - 1 ; i ++ ) { RD(a) ; RD(b) ; RD(c) ; add(a , b , c) ; add(b , a , c) ; in[a] ++ ; in[b] ++ ; } ans = 0 ; dfs(1 , 0 , 0) ; printf("Case #%d: %d\n",++ca , ans) ; } return 0 ; }
C。水题。
#define N 10 int a[2] ,b[2],c[2] , d[2],e[2] ; int main() { int T ; cin >> T ; int ca = 0 ; while(T -- ){ int sum = 0 ; cin >> a[0] >> b[0] >> c[0] >> d[0] >> e[0] ; sum += a[0] + b[0] + c[0] + d[0] + e[0] ; int M ; cin >> M ; printf("Case #%d: ",++ca) ; if(sum >= M){ cout << "0" << endl; continue ; } int num = 0 ; bool flag = 0 ; int x = 1 ; while(1){ a[num ^ 1] = a[num] + b[num] ; b[num ^ 1] = b[num] + c[num] ; c[num ^ 1] = c[num] + d[num] ; d[num ^ 1] = d[num] + e[num] ; e[num ^ 1] = e[num] + a[num] ; int ss = a[num ^ 1] + b[num ^ 1] + c[num ^ 1] + d[num ^ 1] + e[num ^ 1] ; if(ss >= M)break ; else if(ss <= sum){ flag = 1 ;break ; } x ++ ; num ^= 1 ; } if(flag)cout << -1 << endl; else cout << x << endl; } return 0 ; }
D。
E。
F。
G。
直接求出双连通分量,然后缩点之后,对于点数大于等于2的连通分量是不能访问的,所以只要找出所有连通的点数为1的双联通分量的数量,然后C(n , 2)就可以了。
#define N 11111 struct kdq{ int e ,next ; int sign ; }ed[N * 20] , ed1[N * 20] ; int head[N] , num ; int head1[N] , num1 ; void add(int s ,int e){ ed[num].e = e ; ed[num].next = head[s] ; ed[num].sign = 0 ; head[s] = num ++ ; } void add1(int s ,int e){ ed1[num1].e = e ; ed1[num1].next = head1[s] ; ed1[num1].sign = 0 ; head1[s] = num1 ++ ; } int n , m ; int dfn[N] , low[N] , belong[N] , st[N] ,cnt[N] ,vis[N] ; int tp , dp , scc ; void init(){ mem(head ,-1) ; mem(head1, -1) ; num1 = 0 ; num = 0 ; mem(dfn ,-1) ; mem(low ,0) ; mem(belong ,0) ; mem(st ,0) ; mem(cnt ,0) ; tp = dp = scc = 0 ; } void tarjan(int now , int fa){ dfn[now] = low[now] = ++ dp ; st[tp ++ ] = now ; vis[now] = 1 ; for (int i = head[now] ; ~i ; i = ed[i].next ){ int e = ed[i].e ; if(ed[i].sign)continue ; ed[i].sign = ed[i ^ 1].sign = 1 ; if(e == fa)continue ; if(dfn[e] == -1){ tarjan(e , now) ; low[now] = min(low[e] , low[now]) ; } else if(vis[e]){ low[now] = min(low[now] , dfn[e]) ; } } if(dfn[now] == low[now]){ scc ++ ; int xx ; do{ xx = st[-- tp] ; belong[xx] = scc ; cnt[scc] ++ ; vis[xx] = 0 ; }while(xx != now) ; } } int sum = 0 ; void dfs(int now){ for (int i = head1[now] ; ~i ; i = ed1[i].next){ int e = ed1[i].e ; if(!vis[e]){ sum ++ ; vis[e] = 1 ; dfs(e) ; } } } int main() { int T ; cin >> T ; int ca = 0 ; while( T -- ){ cin >> n >> m ; init() ; while(m -- ){ int a , b ; RD(a) ; RD(b) ; add(a , b) ;add(b, a) ; } for (int i = 1 ; i <= n ; i ++ )if(dfn[i] == -1)tarjan(i ,-1) ; mem(vis ,0) ; for (int i = 1 ; i <= n ; i ++ ){ for (int j = head[i] ; ~j ; j = ed[j].next ){ int x = belong[i] ; int y = belong[ed[j].e] ; if(x != y){ add1(x , y) ;add1(y ,x) ; } } } for (int i = 1 ; i <= scc ; i ++ ){ if(cnt[i] >= 2)vis[i] = 1 ; } ll ans = 0 ; for (int i = 1 ; i <= scc ; i ++ ){ if(!vis[i] && cnt[i] == 1){ sum = 1 ; vis[i] = 1 ; dfs(i) ; ans += (ll)sum * (sum - 1) / 2 ; } } printf("Case #%d: %lld\n",++ca ,ans) ; } return 0 ; }
H。
I。
J,水题。