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。
http://blog.csdn.net/just_water/article/details/11006059
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,水题。