A.
显然枚举每个点然后极角排序,然后two-pointer即可。
但是这货写着比较复杂啊。
B.
网络流。首先考虑没有阻挡,那么按行-列建二分图,然后连很多条边费用不同,代表当前的花费,然后最小费用最大流。
如果有阻挡?拆下点就行了。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<queue> #define maxv 200050 #define maxe 400050 #define maxn 55 #define inf 1000000007 using namespace std; int n,k,map[maxn][maxn],bel1[maxn][maxn],bel2[maxn][maxn],cnt[maxv],s=0,t,ans=0,ret=0; int nume=1,g[maxv],dis[maxv],prev[maxv],pree[maxv]; bool vis[maxv]; queue <int> q; struct edge { int v,f,c,nxt; }e[maxe]; char ss[maxn]; void addedge(int u,int v,int f,int c) { e[++nume].v=v;e[nume].f=f;e[nume].c=c;e[nume].nxt=g[u];g[u]=nume; e[++nume].v=u;e[nume].f=0;e[nume].c=-c;e[nume].nxt=g[v];g[v]=nume; } void build() { for (int i=1;i<=n;i++) { int pre=0; for (int j=1;j<=n;j++) { if ((pre^map[i][j]) && (map[i][j])) ret++; if (map[i][j]) {bel1[i][j]=ret;cnt[ret]++;}pre=map[i][j]; } } for (int i=1;i<=ret;i++) for (int j=0;j<cnt[i];j++) addedge(s,i,1,j); int regis=ret+1; for (int j=1;j<=n;j++) { int pre=0; for (int i=1;i<=n;i++) { if ((pre^map[i][j]) && (map[i][j])) ret++; if (map[i][j]) {bel2[i][j]=ret;cnt[ret]++;}pre=map[i][j]; } } for (int i=regis;i<=ret;i++) for (int j=0;j<cnt[i];j++) addedge(i,t,1,j); for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) { if (!map[i][j]) continue; addedge(bel1[i][j],bel2[i][j],1,0); } } void spfa() { while (!q.empty()) q.pop(); for (int i=s;i<=ret;i++) {vis[i]=false;dis[i]=inf;prev[i]=0;pree[i]=0;} dis[s]=0;vis[s]=true;prev[t]=0;pree[t]=0;dis[t]=inf;vis[t]=false;q.push(s); while (!q.empty()) { int head=q.front();q.pop(); for (int i=g[head];i;i=e[i].nxt) { int v=e[i].v; if ((e[i].f>0) && (dis[v]>dis[head]+e[i].c)) { dis[v]=dis[head]+e[i].c; pree[v]=i;prev[v]=head; if (!vis[v]) {vis[v]=true;q.push(v);} } } vis[head]=false; } } int dinic() { int dt=inf,u=t; while (u!=s) { dt=min(dt,e[pree[u]].f); u=prev[u]; } u=t; while (u!=s) { e[pree[u]].f-=dt;e[pree[u]^1].f+=dt; u=prev[u]; } return dis[t]*dt; } int main() { scanf("%d%d",&n,&k);t=200000; for (int i=1;i<=n;i++) { scanf("%s",ss+1); for (int j=1;j<=n;j++) map[i][j]=(ss[j]=='.'); } build(); for (int i=1;i<=k;i++) { spfa(); ans+=dinic(); } printf("%d ",ans); return 0; }
C.
仿佛和什么后缀数组有关。。。弃坑啦。