2018/8/10

一:HDU2807

                                                                   

 The Shortest Path

There are N cities in the country. Each city is represent by a matrix size of M*M. If city A, B and C satisfy that A*B = C, we say that there is a road from A to C with distance 1 (but that does not means there is a road from C to A). 
Now the king of the country wants to ask me some problems, in the format: 
Is there is a road from city X to Y? 
I have to answer the questions quickly, can you help me?

Input

Each test case contains a single integer N, M, indicating the number of cities in the country and the size of each city. The next following N blocks each block stands for a matrix size of M*M. Then a integer K means the number of questions the king will ask, the following K lines each contains two integers X, Y(1-based).The input is terminated by a set starting with N = M = 0. All integers are in the range [0, 80].

Output

For each test case, you should output one line for each question the king asked, if there is a road from city X to Y? Output the shortest distance from X to Y. If not, output "Sorry".

Sample Input

3 2
1 1
2 2
1 1
1 1
2 2
4 4
1
1 3
3 2
1 1
2 2
1 1
1 1
2 2
4 3
1
1 3
0 0

Sample Output

1
Sorry

 

//矩阵和最短路,最短路毫无疑问是floyd算法,矩阵如果用普通的矩阵:矩阵乘法O(n3),矩阵比较O(m2),会超时。

所以要优化矩阵,再增添一个m*1的矩阵remat[n],remat[i]=matrix[i]*  \begin{bmatrix} 1\\ 2 \\ 3 \\ ... \\ m \end{bmatrix} ,题目要求的A*B=C就变成了remat[A的下标]*B=remar[C的下标],这样乘法的复杂度就变成了O(n2),比较复杂度变成了O[m]。代码如下:

#include<iostream>
#include<cstdio>
#include<algorithm>
#define INF 0xffff
using namespace std;
int n,m;
struct matrix
{
    int mp[85][85];
}mat[85];
int edge[85][85];
struct rematrix
{
    int a[85];
}remat[85];
void ok(int x,int y)
{
    for(int i=1;i<=m;i++)
        if(remat[0].a[i]!=remat[y].a[i])return ;
    edge[x][y]=1;
}
void cal(int x,int y)
{
    for(int i=1;i<=m;i++)
    {
        remat[0].a[i]=0;
        for(int j=1;j<=m;j++)
        {
            remat[0].a[i]+=mat[x].mp[i][j]*remat[y].a[j];
        }
    }
    for(int i=1;i<=n;i++)
        if(i!=x&&i!=y)ok(x,i);

}
void floyd()
{
    for(int k=1;k<=n;k++)
        for(int i=1;i<=n;i++)
           for(int j=1;j<=n;j++)
               edge[i][j]=min(edge[i][j],edge[i][k]+edge[k][j]);
}
int main()
{
    while(~scanf("%d%d",&n,&m)&&n&&m)
    {
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
                edge[i][j]=INF;
            edge[i][i]=0;
        }//printf("***\n");
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=m;j++)
            {
                remat[i].a[j]=0;
                for(int k=1;k<=m;k++)
                {
                    scanf("%d",&mat[i].mp[j][k]);
                    remat[i].a[j]+=mat[i].mp[j][k]*k;
                }
            }
        }
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
                if(i!=j)cal(i,j);
        floyd();
        int q;
        cin>>q;

        while(q--)
        {
           // printf("****\n");
            int x,y;
            scanf("%d%d",&x,&y);
            if(edge[x][y]<INF)printf("%d\n",edge[x][y]);
            else printf("Sorry\n");
        }
    }
    return 0;

}

二:hdu1599

find the mincost route

 

杭州有N个景区,景区之间有一些双向的路来连接,现在8600想找一条旅游路线,这个路线从A点出发并且最后回到A点,假设经过的路线为V1,V2,....VK,V1,那么必须满足K>2,就是说至除了出发点以外至少要经过2个其他不同的景区,而且不能重复经过同一个景区。现在8600需要你帮他找一条这样的路线,并且花费越少越好。 

Input

第一行是2个整数N和M(N <= 100, M <= 1000),代表景区的个数和道路的条数。 
接下来的M行里,每行包括3个整数a,b,c.代表a和b之间有一条通路,并且需要花费c元(c <= 100)。

Output

对于每个测试实例,如果能找到这样一条路线的话,输出花费的最小值。如果找不到的话,输出"It's impossible.".

Sample Input

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

Sample Output

3
It's impossible.

//floyd算法

//同一条边输入两次取最小

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
int n,m;
int d[105][105];
int mp[105][105];
int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
             {
                if(i == j)
                {
                    mp[i][j] = d[i][j] = 0;
                }
                else
                {
                    mp[i][j] = d[i][j] = 0xffff;
                }
             }
        for(int i=1;i<=m;i++)
        {
            int a,b,c;
            scanf("%d%d%d",&a,&b,&c);
            mp[a][b]=mp[b][a]=d[a][b]=d[b][a]=min(d[a][b],c);
        }
        int ans=0xffff;
        for(int k=1;k<=n;k++)
        {
            for(int i=1;i<k;i++)
                for(int j=i+1;j<k;j++)
                    ans=min(ans,d[i][j]+mp[j][k]+mp[k][i]);
            for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++)
            d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
        }
        if(ans==0xffff)
            printf("It's impossible.\n");
        else printf("%d\n",ans);
    }
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值