zoukankan      html  css  js  c++  java
  • 图论例题合集(三)(未完成)

    A:LightOJ - 1243 Guardian Knights:题目大意:一个n*n的地图,k个骑士,m个磨坊,一个骑士可以保护多个磨坊,一个磨坊可以被多个骑士保护,每个骑士保护磨坊对应的花费是该骑士到该磨坊的距离,问最少花费 一开始总是想着拆点,写了老半天也没写对,看了眼别人的题解才发现不用拆点,我想大概是因为没有限制吧,很多拆点的题目都是要求某个点只能走一遍什么的。对于这道题,直接连边,源点向骑士连边,费用为0,容量为该骑士能保护的磨坊数量,每个磨坊向汇点连边,容量为1,费用为0,每个磨坊一个骑士来保护就够了,多了的话反而增加花费,然后对图进行遍历,每次遇到骑士,就进行bfs,求出该骑士与每个磨坊的距离,建一条容量为1,费用为距离的边。最后跑一遍费用流即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn = 400;
    const int maxm = 10010;
    const int inf = 0x3f3f3f3f;
    typedef pair<int, int> P;
    struct Node
    {
    	int to;
    	int capa;
    	int cost;
    	int next;
    }edge[maxm];
    int n, k, m;
    int cnt;
    int source, sink;
    int head[maxn];
    char map[maxn][maxn];
    int dis[maxn];
    bool vis[maxn];
    int pre[maxn];
    int rec[maxn];
    int num[maxn];
    bool vis_map[maxn][maxn];
    int diss[maxn][maxn];
    int dirx[] = { 0,1,0,-1 };
    int diry[] = { 1,0,-1,0 };
    int mill[50][50];
    void init()
    {
    	cnt = 0;
    	memset(head, -1, sizeof(head));
    	return;
    }
    void add(int u, int v, int capa, int cost)
    {
    	edge[cnt].to = v;
    	edge[cnt].capa = capa;
    	edge[cnt].cost = cost;
    	edge[cnt].next = head[u];
    	head[u] = cnt++;
    	edge[cnt].to = u;
    	edge[cnt].capa = 0;
    	edge[cnt].cost = -cost;
    	edge[cnt].next = head[v];
    	head[v] = cnt++;
    	return;
    }
    bool spfa()
    {
    	queue<int> que;
    	que.push(source);
    	memset(dis, inf, sizeof(dis));
    	memset(vis, false, sizeof(vis));
    	memset(rec, -1, sizeof(rec));
    	memset(pre, -1, sizeof(pre));
    	dis[source] = 0;
    	vis[source] = true;
    	while (!que.empty())
    	{
    		int node = que.front();
    		que.pop();
    		vis[node] = false;
    		for (int i = head[node]; ~i; i = edge[i].next)
    		{
    			int v = edge[i].to;
    			if (edge[i].capa > 0 && dis[v] > dis[node] + edge[i].cost)
    			{
    				dis[v] = dis[node] + edge[i].cost;
    				rec[v] = i;
    				pre[v] = node;
    				if (!vis[v])
    				{
    					vis[v] = true;
    					que.push(v);
    				}
    			}
    		}
    	}
    	return dis[sink] != inf;
    }
    int mcmf()
    {
    	int mincost = 0;
    	while (spfa())
    	{
    		int node = sink;
    		int flow = inf;
    		while (node != source)
    		{
    			flow = min(flow, edge[rec[node]].capa);
    			node = pre[node];
    		}
    		node = sink;
    		while (node != source)
    		{
    			mincost += flow * edge[rec[node]].cost;
    			edge[rec[node]].capa -= flow;
    			edge[rec[node] ^ 1].capa += flow;
    			node = pre[node];
    		}
    	}
    	return mincost;
    }
    int getIndex(int x, int y)
    {
    	return (x - 1) * n + y;
    }
    void bfs(int x, int y)
    {
    	queue<P> que;
    	que.push(make_pair(x, y));
    	memset(vis_map, false, sizeof(vis_map));
    	diss[x][y] = 0;
    	while (!que.empty())
    	{
    		P now = que.front();
    		que.pop();
    		int tmpx = now.first;
    		int tmpy = now.second;
    		for (int i = 0; i < 4; i++)
    		{
    			int nx = tmpx + dirx[i];
    			int ny = tmpy + diry[i];
    			if (nx >= 1 && nx <= n && ny >= 1 && ny <= n && !vis_map[nx][ny] && map[nx][ny] != '#')
    			{
    				que.push(make_pair(nx, ny));
    				vis_map[nx][ny] = true;
    				diss[nx][ny] = diss[tmpx][tmpy] + 1;
    				if (map[nx][ny] == 'm')
    				{
    					add(map[x][y] - 'A' + 1, mill[nx][ny] + k, 1, diss[nx][ny]);
    				}
    			}
    		}
    	}
    	return;
    }
    int main()
    {
    	//freopen("in.txt","r",stdin);
    	//freopen("out.txt","w",stdout);
    	int test;
    	scanf("%d", &test);
    	for (int cas = 1; cas <= test; cas++)
    	{
    		init();
    		scanf("%d%d%d", &n, &k, &m);
    		getchar();
    		source = 0;
    		sink = k + m + 1;
    		for (int i = 1; i <= n; i++)
    		{
    			scanf("%s", map[i]);
    		}
    		for (int i = 1; i <= k; i++)
    		{
    			scanf("%d", &num[i]);
    			add(source, i, num[i], 0);
    		}
    		for (int i = 1; i <= m; i++)
    		{
    			add(k + i, sink, 1, 0);
    		}
    		int mill_index = 1;
    		for (int i = 1; i <= n; i++)
    		{
    			for (int j = 1; j <= n; j++)
    			{
    				if (map[i][j] == 'm')
    				{
    					mill[i][j] = mill_index++;//磨坊的编号
    				}
    			}
    		}
    		for (int i = 1; i <= n; i++)
    		{
    			for (int j = 1; j <= n; j++)
    			{
    				if (map[i][j] >= 'A' && map[i][j] <= 'Z')
    				{
    					bfs(i, j);
    				}
    			}
    		}
    		printf("Case %d: %d
    ", cas, mcmf());
    	}
    	return 0;
    }

    B:LightOJ - 1198 Karate Competition:题目大意:你的空手道馆要跟别的空手道馆打比赛,每个人都有个技能点,要是技能点比对手的技能点高就加2分,平手加1分,输了不加分。问最多能得多少分 感觉能贪心做,类似于田忌赛马的思路,但是竟然放在了费用流就用费用流做吧..n^2建图,跑费用流即可。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<queue>
    using namespace std;
    const int maxn=1010;
    const int maxm=10010;
    const int inf=0x3f3f3f3f;
    struct Node
    {
        int to;
        int capa;
        int cost;
        int next;
    }edge[maxm];
    int cnt;
    int source,sink;
    int head[maxn];
    int numa[maxn];
    int numb[maxn];
    int dis[maxn];
    bool vis[maxn];
    int rec[maxn];
    int pre[maxn];
    int ldj;
    void init()
    {
        memset(head,-1,sizeof(head));
        cnt=0;
        return;
    }
    void add(int u,int v,int capa,int cost)
    {
        edge[cnt].to=v;
        edge[cnt].capa=capa;
        edge[cnt].cost=cost;
        edge[cnt].next=head[u];
        head[u]=cnt++;
        edge[cnt].to=u;
        edge[cnt].capa=0;
        edge[cnt].cost=-cost;
        edge[cnt].next=head[v];
        head[v]=cnt++;
        return;
    }
    bool spfa()
    {
        memset(vis,false,sizeof(vis));
        memset(dis,inf,sizeof(dis));
        memset(rec,-1,sizeof(rec));
        memset(pre,-1,sizeof(pre));
        queue<int> que;
        que.push(source);
        dis[source]=0;
        vis[source]=true;
        while(!que.empty())
        {
            int node=que.front();
            que.pop();
            vis[node]=false;
            for(int i=head[node];~i;i=edge[i].next)
            {
                int v=edge[i].to;
                if(edge[i].capa>0&&dis[v]>dis[node]+edge[i].cost)
                {
                    dis[v]=dis[node]+edge[i].cost;
                    rec[v]=i;
                    pre[v]=node;
                    if(!vis[v])
                    {
                        vis[v]=true;
                        que.push(v);
                    }
                }
            }
        }
        return dis[sink]!=inf;
    }
    int mcmf()
    {
        int maxflow=0;
        int mincost=0;
        while(spfa())
        {
            int node=sink;
            int flow=inf;
            while(node!=source)
            {
                flow=min(flow,edge[rec[node]].capa);
                node=pre[node];
            }
            node=sink;
            while(node!=source)
            {
                mincost+=flow*edge[rec[node]].cost;
                edge[rec[node]].capa-=flow;
                edge[rec[node]^1].capa+=flow;
                node=pre[node];
            }
        }
        return -mincost;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        //freopen("out.txt","w",stdout);
        int test;
        scanf("%d",&test);
        for(int cas=1;cas<=test;cas++)
        {
            init();
            int n;
            scanf("%d",&n);
            source=0;
            sink=n*2+1;
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&numa[i]);
            }
            for(int i=1;i<=n;i++)
            {
                scanf("%d",&numb[i]);
            }
            for(int i=1;i<=n;i++)
            {
                for(int j=1;j<=n;j++)
                {
                    if(numa[i]<numb[j])
                    {
                        add(i,n+j,1,0);
                    }
                    else if(numa[i]==numb[j])
                    {
                        add(i,n+j,1,-1);
                    }
                    else 
                    {
                        add(i,n+j,1,-2);
                    }
                }
            }
            for(int i=1;i<=n;i++)
            {
                add(source,i,1,0);
                add(n+i,sink,1,0);
            }
            printf("Case %d: %d
    ",cas,mcmf());
        }
        return 0;
    }
  • 相关阅读:
    CATransform3D中m34字段的取值含义
    iOS模拟器分辨率的问题(转载)
    优秀iOS学习网站(待更新)
    内联函数的理解
    UIView的setNeedsLayout, layoutIfNeeded 和 layoutSubviews 方法之间的关系解释
    Flume基础学习
    2019年总结
    Linux基础学习
    Mysql中几种sql的常见用法
    各种设计模式的简单介绍
  • 原文地址:https://www.cnblogs.com/shmilky/p/14089004.html
Copyright © 2011-2022 走看看