130829 周赛

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
",++ 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
",++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
",++ca ,ans) ;
    }
    return 0 ;
}


H。

I。

J,水题。

原文地址:https://www.cnblogs.com/james1207/p/3297241.html