2014年9月28日 星期日

TIOJ 1213 5樹論 之 最遠距點對

找樹的直徑

#include<cstdio>
#include<cstdlib>
#include<vector>
#include<utility>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;
typedef pair<int,int> pii;
vector<pii> link[N];
int H[N];
int n;
int dfs(int fat, int prc){
    vector<int> hv;
    int get_r = 0;
    for(int lx = 0;lx < link[prc].size();lx++){
        int ind = link[prc][lx].first;
        if(fat == ind) continue;
        get_r = max(get_r, dfs(prc, ind));
        hv.push_back(H[ind] + link[prc][lx].second);
    }
    sort(hv.begin(), hv.end());
    int hvc = hv.size();
    if(hvc == 0)
        H[prc] = 0;
    else
        H[prc] = hv[hvc-1];
    if(hvc == 1)
        get_r = max(get_r, hv[hvc-1]);
    else if(hvc >= 2)
        get_r = max(get_r, hv[hvc-1] + hv[hvc-2]);
    return get_r;
}
int main(){
    for(;;){
        scanf("%d", &n);
        if(n == 0)break;
        memset(H, 0, sizeof(H));
        for(int lx=  0;lx < n;lx++)
            link[lx].clear();
        for(int lx = 0;lx < n-1;lx++){
            int a, b, c;
            scanf("%d %d %d", &a, &b, &c); a--, b--;
            link[a].push_back(pii(b, c));
            link[b].push_back(pii(a, c));
        }

        printf("%d\n", dfs(-1, 0));
    }
    return 0;
}

2014年9月26日 星期五

2010-2011 ACM-ICPC Northeastern European Regional Contest Binary Operation

給一個
{0~9}*{0~9} = {0~9} 的表

然後對於兩個正整數,這個二元運算是每位單獨操作
像 ab * cd  =  (a*b)(c*d)

要計算
a*(a+1)*.....(b)

基本上就要算

a*b*b*b.....(n次)



(0*0*...(n次)*1*1*....(n次).....)^k

用倍增法蓋表
然後逐位遞推就OK了

測資超兇QQ 總之最後過了.....

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
#include<utility>
#include<map>
#include<set>
#include<queue>
#include<cmath>
using namespace std;
typedef unsigned long long int int64;
int64 p10[20];
int mm[10][10];
int dmove[10][10][65];
int mmove[10][20][65];
void TLE(){while(1);}
int get_dmove(int a, int p, int64 n){
    int nn = a;
    for(int s = 0;n;s++, n/=2){
        if(n%2)
            nn = dmove[nn][p][s];
        if(s >= 64) TLE();
    }
    return nn;
}
int get_mmove(int a, int c, int64 n){
    int nn = a;
    for(int s = 0;n;s++, n/=2){
        if(n%2)
            nn = mmove[nn][c][s];
        if(s >= 64) TLE();
    }
    return nn;
}
int gain(int64 src, int p){
    return (src/p10[p])%10;
}
int main()
{
    freopen("binary.in", "r", stdin);
    freopen("binary.out", "w", stdout);
    p10[0] = 1; for(int lx = 1;lx <= 19;lx++) p10[lx] = p10[lx-1]*10LL;
    for(int lx = 0;lx < 10;lx++)
        for(int ly = 0;ly < 10;ly++)
            scanf("%d", &mm[lx][ly]);
    for(int lx = 0;lx < 10;lx++)
        for(int ly=  0;ly < 10;ly++)
            dmove[lx][ly][0] = mm[lx][ly];
    for(int ln = 1;ln <= 64;ln++)
        for(int lx = 0;lx < 10;lx++)
            for(int ly = 0;ly < 10;ly++)
                dmove[lx][ly][ln] = dmove[dmove[lx][ly][ln-1]][ly][ln-1];
    for(int lc = 0;lc <= 18;lc++){
        for(int ln = 0;ln <= 64;ln++){
            for(int la = 0;la<10;la++){
                if(ln == 0){
                    int st = la;
                    for(int lx  = 0;lx < 10;lx++)
                        st = get_dmove(st, lx, p10[lc]);
                    mmove[la][lc][0] = st;
                }else{
                    mmove[la][lc][ln] = mmove[mmove[la][lc][ln-1]][lc][ln-1];
                }
            }
        }
    }
    int64 a, b;
    scanf("%I64u %I64u", &a, &b);
    //if(b < 9*p10[17]+5*p10[16] and b > p10[17]) TLE();
    //if(a > b) TLE();
    int64 mao = 0;
    for(int prb = 0;prb <= 18 and p10[prb] <= b;prb++){
        int64 step = b-a;
        int st = gain(a, prb);
        //if(st >= 10) TLE();
        int64 delta1 = p10[prb]-a%p10[prb]-1LL;
        delta1 = min(step, delta1);
        st = get_dmove(st, st, delta1);
        step -= delta1;
        for(int lx = gain(a, prb)+1;lx <= 9;lx++){
            int64 tostep = min(step, p10[prb]);
            st = get_dmove(st, lx, tostep);
            step -= tostep;
        }
        if(step == 0){ mao += st*p10[prb]; continue;}
        int64 down = a/p10[prb]/10LL + 1LL;
        int64 up = b/p10[prb]/10LL;
        if(up < down ) TLE();
        st = get_mmove(st, prb, up-down);
        step -= p10[prb]*(up-down)*10;
        if(step < 0) TLE();
        for(int lx = 0;lx < gain(b, prb);lx++){
            step -= p10[prb];
            st = get_dmove(st, lx, p10[prb]);
            if(step < 0) TLE();
        }
        step -= b%p10[prb]+1;
        st = get_dmove(st, gain(b, prb), b%p10[prb]+1LL);
        if(step) TLE();
        mao += st*p10[prb];
    }
    printf("%I64u\n", mao);
    return 0;
}

2014年9月21日 星期日

UVA 10779 Collectors Problem

題目簡述:
你和一群人都有一些貼紙,然後你想要越多不同種貼紙,所以你設法和這些人做交易
每次交易都是一張貼紙換一張貼紙,交易是成立的若且唯若且(1)你給他的貼紙是他沒有的(2)他給你的貼紙是多出來的

給定初始狀態,問最後最多可以有多少種貼紙?

總之就是設好幾個限制

(1) 固定人,對於每種貼紙都有上限為1的進入限制。
設好一些邊:
(2) 代表貼紙交換的邊
(3) 每種貼紙最多只會流出1張
(4) 每個人願意交出的貼紙是原本的少一個

若這樣設定,每一條流就會是一次貼紙的交換

testdata:

100
2 2
3 1 1 1
2 2 2

2 2
3 1 1 1
2 2 1

3 3
3 1 1 1
2 2 2
2 2 3

2 3
3 1 2 2
2 3 3




#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
#include<utility>
#include<map>
#include<set>
#include<queue>
#include<cmath>
#define INF 100000
using namespace std;
typedef long long int int64;
int indc; int getind(){return indc++;} int getcnt(){return indc;}
struct edge{int a, b, c;}es[500000]; int ecnt;
vector<int> to[100000]; int nn;
void init(int n){
nn = n;
for(int lx = 0;lx < n;lx++)
to[lx].clear();
ecnt = 0;
return;
}
void addedge(int a, int b, int ab, int ba=0){
if((ab == 0) and (ba == 0)) return;
es[ecnt].a = a, es[ecnt].b = b, es[ecnt].c = ab; to[a].push_back(ecnt++);
es[ecnt].a = b, es[ecnt].b = a, es[ecnt].c = ba; to[b].push_back(ecnt++);
return;
}
int dis[100000];
int path[100000];
int post[100000];
int que[100000];
int bfs(int s, int t){
for(int lx = 0;lx < nn;lx++)
dis[lx] = -1, post[lx] = -1;
int qs = 0, qe = 1; que[0] = s, dis[s] = 0;
while(qs < qe){
int gg = que[qs++];
for(int lx = 0;lx < to[gg].size();lx++){
int lind = to[gg][lx];
if(es[lind].c <= 0) continue;
int pind = es[lind].b;
if(dis[pind] != -1) continue;
dis[pind] = dis[gg] + 1;
post[pind] = lind;
que[qe++] = pind;
}
}
if(dis[t] == -1) return 0;
int pgg = t;
int mm = 10000;
int pathcnt = 0;
while(pgg != s){
int lid = post[pgg];
mm = min(mm, es[lid].c);
path[pathcnt++] = lid;
pgg = es[lid].a;
}
for(int lx = 0;lx < pathcnt;lx++){
es[path[lx]].c -= mm;
es[path[lx]^1].c += mm;
}
return mm;
}
int EKarp(int s, int t){
int cc = 0;
for(;;){
int dc = bfs(s, t);
if(dc == 0) break;
cc += dc;
}
return cc;
}
void pes(){
for(int lx = 0;lx < ecnt;lx++)
if(es[lx].c)
printf("%d -> %d w = %d\n", es[lx].a, es[lx].b, es[lx].c);
return;
}
int main()
{
int T;scanf("%d", &T);
for(int lt = 0;lt < T;lt++){
int n, m;scanf("%d %d", &n, &m);
int own[40][100];

memset(own, 0, sizeof(own));
for(int lx = 0;lx < n;lx++){
int acnt = 0;scanf("%d", &acnt);
for(int la = 0;la < acnt;la++){
int inp;scanf("%d", &inp);
own[lx][inp-1]++;
}
}
int pstin[20][30], pstout[20][30], pvin[20][30], pvout[20][30];
int lim[100];
indc = 0;int st = getind(), ed = getind();
for(int lx = 0;lx < m;lx++){
lim[lx] = getind();
//printf("lim%d = %d\n", lx, lim[lx]);
}
for(int lx = 0;lx < n;lx++){
for(int lm = 0;lm < m;lm++){
pstin[lx][lm] = getind();
pstout[lx][lm] = getind();
pvin[lx][lm] = getind();
pvout[lx][lm] = getind();
// printf("%d->%d X %d->%d\n", pvin[lx][lm], pvout[lx][lm], pstin[lx][lm], pstout[lx][lm]);
}
//printf("--\n");
}
init(getcnt());
//printf("pcnt = %d\n", getcnt());
for(int lx = 0;lx < m;lx++){
addedge(st, pstout[0][lx], own[0][lx]);
addedge(lim[lx], ed, 1);
}
for(int lx = 1;lx < n;lx++){
for(int lm = 0;lm < m;lm++){
addedge(pvin[lx][lm], pvout[lx][lm], 1-(own[lx][lm]>0));
if(own[lx][lm] > 1)
addedge(pstin[lx][lm], pstout[lx][lm], own[lx][lm]-1);
}
for(int lm1 = 0;lm1 < m;lm1++)
for(int lm2 = 0;lm2 < m;lm2++)
if(lm1 != lm2)
addedge(pvout[lx][lm1], pstin[lx][lm2], 1);
for(int ly = 1;ly < n;ly++){
if(lx == ly) continue;
for(int lm = 0;lm < m;lm++){
addedge(pstout[lx][lm], pvin[ly][lm], 1);
addedge(pstout[lx][lm], lim[lm], 1);
}
}
}
for(int lx = 1;lx < n;lx++)
for(int lm = 0;lm < m;lm++)
addedge(pstout[0][lm], pvin[lx][lm], 1);
for(int lx = 0;lx < n;lx++)
for(int lm = 0;lm < m;lm++)
addedge(pstout[lx][lm], lim[lm], 1);
//pes();
int ans = EKarp(st, ed);
if(ans > m) printf("%d\n", 1/0);
printf("Case #%d: %d\n", lt+1, ans);
}
return 0;
}

2014年9月20日 星期六

TIOJ 1017 . C.Node of Sequence

O(N)

#include<cstdio>
#include<cstdlib>
int arr[1000005];
bool ch1[1000005];
bool ch2[1000005];
int main(){
    int T;scanf("%d", &T);while(T--){
        int a;scanf("%d", &a);
        for(int lx = 0;lx < a;lx++) scanf("%d", arr+lx);
        int mm1 = arr[0], mm2 = arr[a-1];
        for(int lx = 1;lx < a;lx++){
            ch1[lx] = arr[lx] > mm1;
            if(arr[lx] > mm1) mm1 = arr[lx];
        }
        for(int lx = a-2;lx >= 0;lx--){
            ch2[lx] = arr[lx] < mm2;
            if(arr[lx] < mm2) mm2 = arr[lx];
        }
        int mao = 0;
        for(int lx = 1; lx < a-1;lx++)
            mao += ch1[lx] and ch2[lx];
        printf("%d\n", mao);
    }
    return 0;
}

2014年9月18日 星期四

UVA 563 Crimewave

http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=504

題目大概這樣:
給一個n*m的盤面,和一些格子點
要判斷是否存在一個規劃方法,使得每個點都能走出盤面而不在corner碰撞,
path限定要沿著盤面格子邊邊走。


方法大概這樣: 把每個點當作S,把邊點當作E,每個點限定流量1,每條邊限定流量INF

然後看最大流是否是點的數量

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
#include<utility>
#include<map>
#include<set>
#include<queue>
#include<cmath>
#define INF 100000
using namespace std;
typedef long long int int64;
typedef struct _edge{ int a, b, w;}edge;
edge es[100000]; int ecnt = 0; int s = 0, t = 0;
vector<int> link[100000];
int nn = 0;
void init(int n){
ecnt = 0;
for(int lx =0;lx < n;lx++)
link[lx].clear();
nn = n;
return;
}
void addedge(int a, int b, int ab, int ba = 0){
es[ecnt].a = a, es[ecnt].b = b, es[ecnt].w = ab; ecnt++; link[a].push_back(ecnt-1);
es[ecnt].a = b, es[ecnt].b = a, es[ecnt].w = ba; ecnt++; link[b].push_back(ecnt-1);
return;
}
void printes(){
for(int lx = 0;lx < ecnt;lx++){
printf("%d: %d -> %d w = %d\n", lx, es[lx].a, es[lx].b, es[lx].w);
}
printf("--\n");
}
int dis[10000];
int q[10000];
int path[10000];
int post[10000];
int bfs(int s, int t){
//printf("bfs %d->%d\n", s, t);
for(int lx = 0;lx < nn;lx++)
dis[lx] = -1, post[lx] = -1;
int qs = 0, qe = 1;
q[0] = s;
while(qs < qe){
int gg =  q[qs]; qs++;
//printf("bfs at %d\n", gg);
int get_dis = dis[gg];
for(int lx = 0;lx < link[gg].size();lx++){
int ind = es[link[gg][lx]].b;
//printf("ind = %d\n", ind);
if(dis[ind] == -1 and es[link[gg][lx]].w)
q[qe++] = ind, dis[ind] = get_dis + 1, post[ind] = link[gg][lx];
}
//printf("--\n");
}
if(dis[t] == -1)
return 0;
int pathcnt = 0;
int nowg = t;
int min_f = INF;
//printf("A\n");
while(nowg != s){
int rvlinkind = post[nowg];
//printf("%d\n", rvlinkind);
if(rvlinkind == -1) break;
path[pathcnt++] = rvlinkind;
nowg = es[rvlinkind].a;
//printf("nowg = %d\n", nowg);
//for(int ppp = 0;ppp/10000 < 10000;ppp++);
min_f = min(min_f, es[rvlinkind].w);
}
for(int lx = 0;lx < pathcnt;lx++){
int linkind = path[lx];
//printf("link%d\n", linkind);
es[linkind].w -= min_f;
es[linkind^1].w += min_f;
}
return min_f;
}
int Ekarp(int s, int t){
int v = 0;
int mao = 0;
while(1){
v = bfs(s, t);
//printf("%d\n", v);
if(v == 0) break;
mao += v;
}
return mao;
}
int chmap[55][55];
int ss, aa;
int get_index(int x, int y){return y*ss + x;}
int main()
{
int T;scanf("%d", &T);
while(T-->0){
int n;scanf("%d %d %d", &ss, &aa, &n);
init(2*ss*aa + 2);
memset(chmap, 0, sizeof(chmap));
for(int lx = 0;lx < n;lx++){
int p, q;scanf("%d %d", &p, &q);
p--, q--; chmap[p][q] = 1;
}
int sss = 2*ss*aa, eee = 2*ss*aa+1;
for(int lx = 0;lx < ss;lx++)
for(int ly = 0;ly < aa;ly++)
if(chmap[lx][ly] == 0)
addedge(2*get_index(lx, ly), 2*get_index(lx, ly)+1, 1-chmap[lx][ly]);

for(int lx = 0;lx+1 < ss;lx++){
for(int ly = 0;ly < aa;ly++){
addedge(2*get_index(lx, ly)+1, 2*get_index(lx+1, ly), INF);
addedge(2*get_index(lx+1, ly)+1, 2*get_index(lx, ly), INF);
}
}
for(int lx = 0;lx < ss;lx++){
for(int ly = 0;ly+1 < aa;ly++){
addedge(2*get_index(lx, ly+1)+1, 2*get_index(lx, ly), INF);
addedge(2*get_index(lx, ly)+1, 2*get_index(lx, ly+1), INF);
}
}
for(int lx = 0;lx < ss;lx++){
for(int ly = 0;ly < aa;ly++){
if((lx == 0) or (ly == 0) or (lx == ss-1) or (ly == aa-1))
addedge(2*get_index(lx, ly)+1, eee, INF);
if(chmap[lx][ly])
addedge(sss, 2*get_index(lx, ly)+1, 1);
}
}
//printes();
puts(Ekarp(sss, eee) == n ? "possible" : "not possible");
}
return 0;
}


2014年9月17日 星期三

TIOJ 1794 Count On a Tribe


給一個陣列,問最大同色面積

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<vector>
#include<utility>
#include<map>
#include<set>
#include<queue>
#include<cmath>
using namespace std;
typedef long long int int64;
typedef pair<int, int> pii;
int arr[3010][3010];
bool vis[3010][3010];
pii q[9000010];
int main()
{
 int n, m;scanf("%d %d", &n, &m);
 for(int lx = 0;lx < n;lx++)
  for(int ly = 0;ly < m;ly++)
   scanf("%d", &arr[lx+1][ly+1]);
 memset(vis, false, sizeof(vis));
 for(int lx = 0;lx <= n+1;lx++)
  arr[lx][0] = -1, arr[lx][m+1] = -1;
 for(int ly = 0;ly <= m+1;ly++)
  arr[0][ly] = -1, arr[n+1][ly] = -1;
 int mao = 0;
 for(int lx = 1;lx <= n;lx++){
  for(int ly = 1;ly <= m;ly++){
   if(vis[lx][ly]) continue;
   int st = 0, ed = 1;
   int typ = arr[lx][ly];
   q[0] = pii(lx, ly);
   vis[lx][ly] = true;
   int cnt = 0;
   while(st < ed){
    int px = q[st].first, py = q[st].second; st++;
    cnt++;
    if(vis[px+1][py] == false and typ == arr[px+1][py])
     vis[px+1][py] = true, q[ed++] = pii(px+1, py);
    if(vis[px-1][py] == false and typ == arr[px-1][py])
     vis[px-1][py] = true, q[ed++] = pii(px-1, py);
    if(vis[px][py-1] == false and typ == arr[px][py-1])
     vis[px][py-1] = true, q[ed++] = pii(px, py-1);
    if(vis[px][py+1] == false and typ == arr[px][py+1])
     vis[px][py+1] = true, q[ed++] = pii(px, py+1);
   }
   mao = max(mao, cnt);
  }
 }
 printf("%d\n", mao);
 return 0;
}