PKU演習問メモ(11/1)
No. | 問題名 | 問題の種類および解法 | 難易度 |
---|---|---|---|
1195 | Mobile phones | Binary Indexed Tree | ★★★☆☆ |
1087 | A Plug for UNIX | 最大流 | ★★☆☆☆ |
2378 | Tree Cutting | 木DP | ★★☆☆☆ |
1195 Mobile phones
問題概要
解法
二次元BITの作り方がわからなかったのでBITを1024個並べたら通ってしまった(酷
http://www.topcoder.com/tc?module=Static&d1=tutorials&d2=binaryIndexedTrees
↑後で読む
ソースコード
int bit[1024][1025],n; int sum(int y,int i){ int s=0; for(;i>0;i-=i&-i)s+=bit[y][i]; return s; } void add(int y,int i,int x) { for(;i<=n;i+=i&-i)bit[y][i]+=x; } int main() { int is,a,b,c,d; scanf("%d%d",&is,&n); while(scanf("%d",&is),is!=3) { if(is==1) { scanf("%d%d%d",&a,&b,&c); add(b,a+1,c); continue; } int s=0; scanf("%d%d%d%d",&a,&b,&c,&d); for(int y=b;y<=d;y++)s+=sum(y,c+1)-sum(y,a); printf("%d\n",s); } return 0; }
1087 A Plug for UNIX
問題概要
解法
最大流。変換機は無限に使えることに注意しないとWA.
ソースコード
void add(Graph &g,int s,int t,int w) { g[s].pb(Edge(s,t,w)); g[t].pb(Edge(t,s,0)); } int n,m,k; vector<string> vs; map<string,int> id; int main() { int e[300][300]={0}; int l=2; //0:source 1:sink string s,t; cin>>n; rep(i,n) { cin>>s,id[s]=l++; e[id[s]][1]++; } cin>>m; rep(i,m) { cin>>t>>s; if(!id.count(s))id[s]=l++; e[0][id[s]]++; } cin>>k; rep(i,k) { cin>>s>>t; e[id[s]][id[t]]=inf; } Graph g(l); rep(i,l)rep(j,l)if(e[i][j])add(g,i,j,e[i][j]); cout<<m-maximumFlow(g,0,1)<<endl; return 0; }
2378 Tree Cutting
問題概要
解法
ある頂点のサブツリーの頂点数をdp[i]とすると、O(n)でdpが求まる。
頂点が条件を満たす⇔その頂点から伸びる頂点以下のサブツリーの頂点数がn/2以下。
ソースコード
int n,dp[10000],ans[10000],na; vector<vi> e; void rec(int c,int p) { dp[c]=1; fr(i,e[c])if(*i!=p)rec(*i,c),dp[c]+=dp[*i]; if(n-dp[c]>n/2)return; fr(i,e[c])if(*i!=p&&dp[*i]>n/2)return; ans[na++]=c; } int main() { scanf("%d",&n); int a,b; e.resize(n); rep(i,n-1) { scanf("%d%d",&a,&b); a--; b--; e[a].pb(b); e[b].pb(a); } rec(0,-1); sort(ans,ans+na); rep(i,na)printf("%d\n",ans[i]+1); return 0; }