4300 一开始向到了后缀数组, 后来才弱爆了发现是kmp的变形, 修改下匹配的起点, 并且返回的是文本串匹配完时模式串当前的位置就可以了, 比赛的时候真是弱爆了T.T
#include <cstring>
#include <cstdio>
using namespace std;
const int maxn=100000+5;
char pat[maxn], str[maxn];
int P[maxn];
/// need *P, *pat and *str
int kmp()
{
int i, j;
int len=strlen(str);
for (P[0]=-1,i=1; pat[i]; ++i)
{
for (j=P[i-1]; j>=0 && pat[i]!=pat[j+1]; j=P[j]);
if(pat[j+1]==pat[i])P[i]=j+1;
}
for (i=(len+1)/2, j=-1; str[i]; ++i)
{
while (j>=0 && pat[j+1]!=str[i])j=P[j];
if(pat[j+1]==str[i])++j;
// if(pat[j+1]==0)
// return i-j;/// return the first pos
}
return i-j-1;
}
char s[40];
char ss[40];
int main()
{
int cas; scanf("%d", &cas);
while (cas--)
{
scanf("%s%s", s, str);
for (int j=0; j<26; ++j)
ss[s[j]-'a']=j+'a';
for (int i=0; str[i]; ++i)
{
pat[i]=ss[str[i]-'a'];
}
int len=strlen(str); pat[len]='\0';
//printf("%s %s\n", pat, str);
int ans=kmp();
for (int i=0; i<ans; ++i)
printf("%c", str[i]);
for (int i=0; i<ans; ++i)
printf("%c", pat[i]);
puts("");
}
return 0;
}
4303 赤裸裸的树形dp, 连推带敲带调,花2、3个小时, 很威武的题
#include <cstdio>
#include <cstring>
#include <iostream>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <stack>
#include <map>
#include <queue>
const double pi=cos(-1.);
const double eps=10e-6;
const double eps1=10e-10;
const int inf=0x7fffffff;
const int inff=2021161080; /// memset 120!
const long long infl=1ll<<62;
///******macro defination******///
#define cas(a) int a; scanf("%d", &a); while (a--)
#define cas1(x, a) int a; scanf("%d", &a); for (int x=1; x<=a; ++x)
#define int(a) int a; scanf("%d", &a)
#define char(a) char a; scanf("%c", &a)
#define strr(a, x) char a[x]; scanf("%s", &a)
#define clean(a) memset (a, 0, sizeof(a));
#define up(x,a) for(int x=0; x<a; ++x)
#define down(x,a) for(int x=a-1; x>=0; --x)
#define up1(x,a) for (int x=1; x<=a; ++x)
#define debug(a) printf("here is %d!!!\n", a);
///*** mathmatics ***///
#define sqr(x) (x)*(x)
#define abs(x) (x)>0?(x):(-(x))
#define zero(x) (x)<eps && (x)>eps
///****** by Geners ******///
typedef long long ll;
typedef unsigned int UI;
using namespace std;
const int maxn=300000+123;
int node[maxn];
struct Edge{
int v, color, next;
}edge[maxn<<1];
int cnt, head[maxn];
void addedge(int u, int v, int w)
{
edge[cnt].color=w;
edge[cnt].v=v;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].color=w;
edge[cnt].v=u;
edge[cnt].next=head[v];
head[v]=cnt++;
}
void init()
{
cnt=0;
memset (head, -1, sizeof(head));
}
ll num[maxn], sum[maxn];
ll ans;
/** 子节点返回给父节点的值是与父节点能构成的路径数num
* 以及能与父节点构成路径的所有路径的结点和sum。
* sum 根据pcolor来求
* 子节点之间怎么办? 思考中。。。map!
**/
void dfs(int u, int fa, int pw)
{
num[u]=1;
sum[u]=node[u];
map<int, pair<ll, ll> >son;
map<int, pair<ll, ll> >::iterator it;
ll cou=0, pro=0;
for (int p=head[u]; ~p; p=edge[p].next)
{
const int &v=edge[p].v, &w=edge[p].color;
if(v==fa)continue;
dfs(v, u, w);
//printf("v=%d u=%d ans==%lld\n", v+1, u+1, ans);
if(w!=pw)
{
num[u]+=num[v];
sum[u]+=sum[v]+node[u]*num[v];
}
cou+=num[v];
if(son.find(w)==son.end())
{
pair<int, int> ii;
ii.first = num[v];
ii.second = sum[v];
son[w]=ii;
}
else
{
son[w].first+=num[v];
son[w].second+=sum[v];
}
//ans+=sum[u];
ans+=sum[v]+node[u]*num[v];
}
//printf("%d cou==%lld totol==%lld\n", u+1, cou, totol);
for (it=son.begin(); it!=son.end(); it++)
{
ll c=it->second.first, s=it->second.second;
pro+=node[u]*(cou-c)*c;
ans+=s*(cou-c);
//printf("c==%lld s==%lld pro==%lld ans==%lld tmp==%lld\n", c, s, pro, ans, s*(cou-c));
}
ans+=pro/2;
//ans+=sum[u];
//printf("u==%d, ans==%lld\n", u+1, ans);
}
int main ()
{
int n;
while (~scanf("%d", &n))
{
init();
for (int i=0; i<n; ++i) scanf("%d", node+i);
for (int i=1; i<n; ++i)
{
int a, b, c; scanf("%d%d%d", &a, &b, &c);
addedge(a-1, b-1, c);
}
ans=0;
dfs(0, -1, -1);
printf("%I64d\n", ans);
}
return 0;
}
/*
6
6 2 3 7 1 4
1 2 1
1 3 2
1 4 3
2 5 1
2 6 2
3
1 2 3
1 2 1
2 3 2
3
1 2 0
1 2 1
2 3 1
4
1 2 3 4
1 2 1
2 3 2
3 4 1
7
6 2 3 7 1 4 1
1 2 1
1 3 2
1 4 3
2 5 1
2 6 2
5 7 2
*/
4309 网络流,
三种边, 桥, 路, 隧道, 连接各个城市, 很容易想到对隧道的处理, 关键是桥的费用的问题, 一直没想到怎么处理, 看到题解说是桥的个数小于等于12,直接暴力枚举,跑2^12次最大流,瞬间巨无语,敲完交, 直接跪, 调半天看题解, 发现对桥的处理还有一个当不修桥还可以通过一人,回去一个题意还真是,直接给题意跪了。
http://acm.hdu.edu.cn/showproblem.php?pid=4309
又新敲了遍sap
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int inf=0x7fffffff;
const int N=200;
const int M=10000;
struct Edge{
int v, next, w;
}edge[M<<2];
int cnt, head[N];
void addedge(int u, int v, int w)
{
edge[cnt].v=v;
edge[cnt].w=w;
edge[cnt].next=head[u];
head[u]=cnt++;
edge[cnt].v=u;
edge[cnt].w=0;
edge[cnt].next=head[v];
head[v]=cnt++;
}
int sap(int s, int t)
{
int pre[N], cur[N], dis[N], gap[N];
int flow=0, aug=inf, u;
bool flag;
for (int i=0; i<=t; ++i)
{
cur[i]=head[i], gap[i]=dis[i]=0;
}
u=pre[s]=s; gap[s]=t+1;/// 倒序分层
while(dis[s]<=t)
{
flag=false;
for (int &p=cur[u]; ~p; p=edge[p].next)
{/// 从当前弧开始寻找
const int &v=edge[p].v, &w=edge[p].w;
if(w>0 && dis[u]==dis[v]+1)
{
flag=true;
if(w<aug)aug=w;///寻找增广路上的最小值
pre[v]=u; u=v;
if(u==t)/// 如果增广到汇点
{
for (flow+=aug; u!=s;)
{
u=pre[u];
edge[cur[u]].w-=aug;
edge[cur[u]^1].w+=aug;
}
aug=inf;
}
break;
}
}
if(flag)continue;/// 直到未找到增广路
int mindis=t+1;
for (int p=head[u]; ~p; p=edge[p].next)
{///当前弧优化的理解还是不太到位
const int &v=edge[p].v, &w=edge[p].w;
if(w>0 && dis[v]<mindis)
mindis=dis[v], cur[u]=p;
}
if(--gap[dis[u]]==0)break;
gap[dis[u]=mindis+1]++;
u=pre[u];
}
return flow;
}
void init()
{
cnt=0;
memset(head, -1, sizeof(head));
}
int a[M], b[M], c[M], total;
void build()
{
init();
for (int i=0; i<total; ++i)
{
addedge(a[i], b[i], c[i]);
}
}
int bu[20], bv[20], bc[20];
int main()
{
int n, m;
while (~scanf("%d%d", &n, &m))
{
total=0;
int t=n, bridge=0;
for (int i=1; i<=n; ++i)
{
int v; scanf("%d", &v);
a[total]=0; b[total]=i; c[total++]=v;
}
for (int i=0; i<m; ++i)
{
int u, v, w, p; scanf("%d%d%d%d", &u, &v, &w, &p);
if(p==0)
{
a[total]=u, b[total]=v, c[total++]=inf;
//a[total]=v, b[total]=u, c[total++]=inf;
}else
if(p<0)
{
t++;
a[total]=u, b[total]=t, c[total++]=inf;
a[total]=t, b[total]=v, c[total++]=inf;
a[total]=t, b[total]=151, c[total++]=w;
}else
{
bu[bridge]=u, bv[bridge]=v, bc[bridge++]=w;
}
}
int ans=-1, cost=inf;
for (int i=0; i<(1<<bridge); ++i)
{
build();
int tmpc=0;
for (int j=0; j<bridge; ++j)
{
if(i&(1<<j))
{
tmpc+=bc[j];
addedge(bu[j], bv[j], inf);
//addedge(bv[j], bu[j], inf);
}
else addedge(bu[j], bv[j], 1);
}
int tmpa=sap(0, 151);
if(tmpa==ans) cost=min(cost, tmpc);
if(tmpa>ans)
{
ans=tmpa;
cost=tmpc;
}
//printf("%d %d %d\n", i, ans, cost);
}
if(ans>0)
printf("%d %d\n", ans, cost);
else
puts("Poor Heaven Empire");
}
return 0;
}